Skip to content

Commit 5394868

Browse files
authored
Merge pull request #726 from repko-artem/master
Add support for JSON Schema $defs, definitions, $ref, oneOf, anyOf and others in PropertyDefinition
2 parents 731b7c5 + ba5de8f commit 5394868

File tree

2 files changed

+186
-6
lines changed

2 files changed

+186
-6
lines changed

OpenAI.SDK/ObjectModels/Converters.cs

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,51 @@ public override void Write(Utf8JsonWriter writer, AssistantsApiToolChoiceOneOfTy
8989
writer.WriteNullValue();
9090
}
9191
}
92-
}
92+
}
93+
94+
public class SingleOrArrayToListConverter : JsonConverter<IList<string?>>
95+
{
96+
public override IList<string?>? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
97+
switch (reader.TokenType) {
98+
case JsonTokenType.String:
99+
return [reader.GetString()];
100+
case JsonTokenType.StartArray:
101+
{
102+
var list = new List<string?>();
103+
while (reader.Read() && reader.TokenType != JsonTokenType.EndArray) {
104+
switch (reader.TokenType) {
105+
case JsonTokenType.String:
106+
list.Add(reader.GetString());
107+
break;
108+
case JsonTokenType.Null:
109+
list.Add(null);
110+
break;
111+
default:
112+
throw new JsonException($"Unexpected token in type array: {reader.TokenType}");
113+
}
114+
}
115+
return list;
116+
}
117+
default:
118+
throw new JsonException($"Unexpected token parsing type: {reader.TokenType}");
119+
}
120+
}
121+
122+
public override void Write(Utf8JsonWriter writer, IList<string?>? value, JsonSerializerOptions options) {
123+
if (value == null || value.Count == 0) {
124+
writer.WriteNullValue();
125+
} else if (value.Count == 1) {
126+
writer.WriteStringValue(value[0]);
127+
} else {
128+
writer.WriteStartArray();
129+
foreach (var item in value) {
130+
if (item == null) {
131+
writer.WriteNullValue();
132+
} else {
133+
writer.WriteStringValue(item);
134+
}
135+
}
136+
writer.WriteEndArray();
137+
}
138+
}
139+
}

OpenAI.SDK/ObjectModels/SharedModels/FunctionParameters.cs

Lines changed: 138 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System.Text.Json.Serialization;
1+
using System.Text.Json.Serialization;
22

33
namespace Betalgo.Ranul.OpenAI.ObjectModels.SharedModels;
44

@@ -20,10 +20,33 @@ public enum FunctionObjectTypes
2020
}
2121

2222
/// <summary>
23-
/// Required. Function parameter object type. Default value is "object".
23+
/// Property's type as a string. Only one: <see cref="TypeList"/> or <see cref="Type"/> should be set.
24+
/// </summary>
25+
[JsonIgnore]
26+
public string? Type {
27+
get => TypeList?.Count != 1 ? null : TypeList[0];
28+
set {
29+
if (value == null) {
30+
TypeList = null;
31+
return;
32+
}
33+
TypeList = [value];
34+
}
35+
}
36+
37+
/// <summary>
38+
/// Property's type as a list of strings. Only one: <see cref="TypeList"/> or <see cref="Type"/> should be set.
2439
/// </summary>
2540
[JsonPropertyName("type")]
26-
public string Type { get; set; } = "object";
41+
[JsonConverter(typeof(SingleOrArrayToListConverter))]
42+
public IList<string?>? TypeList { get; set; }
43+
44+
/// <summary>
45+
/// An instance validates successfully against this keyword if its value is equal to the value of the keyword
46+
/// https://json-schema.org/draft/2020-12/json-schema-validation#name-const
47+
/// </summary>
48+
[JsonPropertyName("const")]
49+
public string? Constant { get; set; }
2750

2851
/// <summary>
2952
/// Optional. List of "function arguments", as a dictionary that maps from argument name
@@ -45,7 +68,15 @@ public enum FunctionObjectTypes
4568
public bool? AdditionalProperties { get; set; }
4669

4770
/// <summary>
48-
/// Optional. Argument description.
71+
/// Optional. Title of the schema.
72+
/// https://json-schema.org/draft/2020-12/json-schema-validation#name-title-and-description
73+
/// </summary>
74+
[JsonPropertyName("title")]
75+
public string? Title { get; set; }
76+
77+
/// <summary>
78+
/// Optional. Description of the schema.
79+
/// https://json-schema.org/draft/2020-12/json-schema-validation#name-title-and-description
4980
/// </summary>
5081
[JsonPropertyName("description")]
5182
public string? Description { get; set; }
@@ -69,6 +100,74 @@ public enum FunctionObjectTypes
69100
/// </summary>
70101
[JsonPropertyName("maxProperties")]
71102
public int? MaxProperties { get; set; }
103+
104+
/// <summary>
105+
/// The value of "multipleOf" MUST be a number, strictly greater than 0.
106+
/// A numeric instance is valid only if division by this keyword's value results in an integer.
107+
/// https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-00#rfc.section.6.2.1
108+
/// </summary>
109+
[JsonPropertyName("multipleOf")]
110+
public float? MultipleOf { get; set; }
111+
112+
/// <summary>
113+
/// The value of "minimum" MUST be a number, representing an inclusive lower limit for a numeric instance.
114+
/// https://json-schema.org/draft/2020-12/json-schema-validation#name-minimum
115+
/// </summary>
116+
[JsonPropertyName("minimum")]
117+
public float? Minimum { get; set; }
118+
119+
/// <summary>
120+
/// The value of "exclusiveMinimum" MUST be a number, representing an exclusive lower limit for a numeric
121+
/// instance. If the instance is a number, then the instance is valid only if it has a value strictly greater
122+
/// than (not equal to) "exclusiveMinimum".
123+
/// https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-00#rfc.section.6.2.5
124+
/// </summary>
125+
[JsonPropertyName("exclusiveMinimum")]
126+
public float? ExclusiveMinimum { get; set; }
127+
128+
/// <summary>
129+
/// The value of "maximum" MUST be a number, representing an inclusive upper limit for a numeric instance.
130+
/// https://json-schema.org/draft/2020-12/json-schema-validation#name-maximum
131+
/// </summary>
132+
[JsonPropertyName("maximum")]
133+
public float? Maximum { get; set; }
134+
135+
/// <summary>
136+
/// The value of "exclusiveMaximum" MUST be a number, representing an exclusive upper limit for a numeric
137+
/// instance. If the instance is a number, then the instance is valid only if it has a value strictly less than
138+
/// (not equal to) "exclusiveMaximum".
139+
/// https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-00#rfc.section.6.2.3
140+
/// </summary>
141+
[JsonPropertyName("exclusiveMaximum")]
142+
public float? ExclusiveMaximum { get; set; }
143+
144+
/// <summary>
145+
/// Predefined formats for strings. Currently supported:
146+
/// date-time, time, date, duration, email, hostname, ipv4, ipv6, uuid
147+
/// </summary>
148+
[JsonPropertyName("format")]
149+
public string? Format { get; set; }
150+
151+
/// <summary>
152+
/// A regular expression that the string must match.
153+
/// https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-00#pattern
154+
/// </summary>
155+
[JsonPropertyName("pattern")]
156+
public string? Pattern { get; set; }
157+
158+
/// <summary>
159+
/// The array must have at least this many items.
160+
/// https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-00#rfc.section.6.4.2
161+
/// </summary>
162+
[JsonPropertyName("minItems")]
163+
public int? MinItems { get; set; }
164+
165+
/// <summary>
166+
/// The array must have at most this many items.
167+
/// https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-00#rfc.section.6.4.4
168+
/// </summary>
169+
[JsonPropertyName("maxItems")]
170+
public int? MaxItems { get; set; }
72171

73172
/// <summary>
74173
/// If type is "array", this specifies the element type for all items in the array.
@@ -77,6 +176,40 @@ public enum FunctionObjectTypes
77176
/// </summary>
78177
[JsonPropertyName("items")]
79178
public PropertyDefinition? Items { get; set; }
179+
180+
/// <summary>
181+
/// Definitions of schemas (2020-12 and newer specifications).
182+
/// For more details, see https://json-schema.org/understanding-json-schema/structuring#defs
183+
/// </summary>
184+
[JsonPropertyName("$defs")]
185+
public IDictionary<string, PropertyDefinition>? Defs { get; set; }
186+
187+
/// <summary>
188+
/// Definitions of schemas (draft-07 specification).
189+
/// </summary>
190+
[JsonPropertyName("definitions")]
191+
public IDictionary<string, PropertyDefinition>? Definitions { get; set; }
192+
193+
/// <summary>
194+
/// Reference to another schema definition.
195+
/// For more details, see https://json-schema.org/understanding-json-schema/structuring#dollarref
196+
/// </summary>
197+
[JsonPropertyName("$ref")]
198+
public string? Ref { get; set; }
199+
200+
/// <summary>
201+
/// To validate against anyOf, the given data must be valid against any (one or more) of the given subschemas.
202+
/// For more details, see https://json-schema.org/understanding-json-schema/reference/combining#anyOf
203+
/// </summary>
204+
[JsonPropertyName("anyOf")]
205+
public IList<PropertyDefinition>? AnyOf { get; set; }
206+
207+
/// <summary>
208+
/// To validate against oneOf, the given data must be valid against exactly one of the given subschemas.
209+
/// For more details, see https://json-schema.org/understanding-json-schema/reference/combining#oneOf
210+
/// </summary>
211+
[JsonPropertyName("oneOf")]
212+
public IList<PropertyDefinition>? OneOf { get; set; }
80213

81214
public static PropertyDefinition DefineArray(PropertyDefinition? arrayItems = null)
82215
{
@@ -174,4 +307,4 @@ public static string ConvertTypeToString(FunctionObjectTypes type)
174307
_ => throw new ArgumentOutOfRangeException(nameof(type), $"Unknown type: {type}")
175308
};
176309
}
177-
}
310+
}

0 commit comments

Comments
 (0)