Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions src/models/v3.0/schema.zig
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@ const json = std.json;
const Reference = @import("reference.zig").Reference;
const ExternalDocumentation = @import("externaldocs.zig").ExternalDocumentation;

fn optionalFloat(value: ?json.Value) ?f64 {
const val = value orelse return null;
return switch (val) {
.integer => |i| @as(f64, @floatFromInt(i)),
.float => |f| f,
.number_string => |s| std.fmt.parseFloat(f64, s) catch null,
else => null,
};
}

pub const XML = struct {
name: ?[]const u8 = null,
namespace: ?[]const u8 = null,
Expand Down Expand Up @@ -182,10 +192,10 @@ pub const Schema = struct {
}
return Schema{
.title = if (obj.get("title")) |val| try allocator.dupe(u8, val.string) else null,
.multipleOf = if (obj.get("multipleOf")) |val| val.float else null,
.maximum = if (obj.get("maximum")) |val| val.float else null,
.multipleOf = optionalFloat(obj.get("multipleOf")),
.maximum = optionalFloat(obj.get("maximum")),
.exclusiveMaximum = if (obj.get("exclusiveMaximum")) |val| val.bool else null,
.minimum = if (obj.get("minimum")) |val| val.float else null,
.minimum = optionalFloat(obj.get("minimum")),
.exclusiveMinimum = if (obj.get("exclusiveMinimum")) |val| val.bool else null,
.maxLength = if (obj.get("maxLength")) |val| val.integer else null,
.minLength = if (obj.get("minLength")) |val| val.integer else null,
Expand Down
16 changes: 13 additions & 3 deletions src/models/v3.2/schema.zig
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@ const json = std.json;
const Reference = @import("reference.zig").Reference;
const ExternalDocumentation = @import("externaldocs.zig").ExternalDocumentation;

fn optionalFloat(value: ?json.Value) ?f64 {
const val = value orelse return null;
return switch (val) {
.integer => |i| @as(f64, @floatFromInt(i)),
.float => |f| f,
.number_string => |s| std.fmt.parseFloat(f64, s) catch null,
else => null,
};
}

pub const XML = struct {
name: ?[]const u8 = null,
namespace: ?[]const u8 = null,
Expand Down Expand Up @@ -206,10 +216,10 @@ pub const Schema = struct {

return Schema{
.title = if (obj.get("title")) |val| try allocator.dupe(u8, val.string) else null,
.multipleOf = if (obj.get("multipleOf")) |val| val.float else null,
.maximum = if (obj.get("maximum")) |val| val.float else null,
.multipleOf = optionalFloat(obj.get("multipleOf")),
.maximum = optionalFloat(obj.get("maximum")),
.exclusiveMaximum = if (obj.get("exclusiveMaximum")) |val| val.bool else null,
.minimum = if (obj.get("minimum")) |val| val.float else null,
.minimum = optionalFloat(obj.get("minimum")),
.exclusiveMinimum = if (obj.get("exclusiveMinimum")) |val| val.bool else null,
.maxLength = if (obj.get("maxLength")) |val| val.integer else null,
.minLength = if (obj.get("minLength")) |val| val.integer else null,
Expand Down
17 changes: 17 additions & 0 deletions src/tests/openapi_v32_tests.zig
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const OpenApi32Converter = @import("../generators/converters/openapi32_converter.zig").OpenApi32Converter;
const models = @import("../models.zig");
const std = @import("std");
const json = std.json;
const test_utils = @import("test_utils.zig");

fn loadOpenApi32Document(allocator: std.mem.Allocator, file_path: []const u8) !models.OpenApi32Document {
Expand All @@ -26,6 +27,22 @@ test "can deserialize petstore into OpenApi32Document" {
try std.testing.expectEqualStrings("Swagger Petstore", parsed.info.title);
}

test "schema numeric bounds accept integer and number_string values for v3.2" {
var gpa = test_utils.createTestAllocator();
const allocator = gpa.allocator();
var object = json.ObjectMap.init(allocator);
defer object.deinit();
try object.put("type", .{ .string = "number" });
try object.put("multipleOf", .{ .integer = 2 });
try object.put("maximum", .{ .integer = 10 });
try object.put("minimum", .{ .number_string = "1.5" });
var schema = try models.v32.Schema.parseFromJson(allocator, .{ .object = object });
defer schema.deinit(allocator);
try std.testing.expectEqual(@as(f64, 2.0), schema.multipleOf.?);
try std.testing.expectEqual(@as(f64, 10.0), schema.maximum.?);
try std.testing.expectEqual(@as(f64, 1.5), schema.minimum.?);
}

test "can parse petstore info summary field" {
var gpa = test_utils.createTestAllocator();
const allocator = gpa.allocator();
Expand Down
17 changes: 17 additions & 0 deletions src/tests/openapi_v3_tests.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const ModelCodeGenerator = @import("../generators/v3.0/modelgenerator.zig").Mode
const OpenApiConverter = @import("../generators/converters/openapi_converter.zig").OpenApiConverter;
const models = @import("../models.zig");
const std = @import("std");
const json = std.json;
const test_utils = @import("test_utils.zig");

fn loadOpenApiDocument(allocator: std.mem.Allocator, file_path: []const u8) !models.OpenApiDocument {
Expand All @@ -27,6 +28,22 @@ test "can deserialize petstore into OpenApiDocument" {
try std.testing.expectEqualStrings("Swagger Petstore", parsed.info.title);
}

test "schema numeric bounds accept integer and number_string values" {
var gpa = test_utils.createTestAllocator();
const allocator = gpa.allocator();
var object = json.ObjectMap.init(allocator);
defer object.deinit();
try object.put("type", .{ .string = "number" });
try object.put("multipleOf", .{ .integer = 2 });
try object.put("maximum", .{ .integer = 10 });
try object.put("minimum", .{ .number_string = "1.5" });
var schema = try models.v3.Schema.parseFromJson(allocator, .{ .object = object });
defer schema.deinit(allocator);
try std.testing.expectEqual(@as(f64, 2.0), schema.multipleOf.?);
try std.testing.expectEqual(@as(f64, 10.0), schema.maximum.?);
try std.testing.expectEqual(@as(f64, 1.5), schema.minimum.?);
}

test "can generate data structures from petstore OpenAPI specification" {
var gpa = test_utils.createTestAllocator();
const allocator = gpa.allocator();
Expand Down
Loading