Skip to content

Commit 4a7e0c9

Browse files
authored
[nim] Nim Generator Fixes (#22385)
* Nim Generator Fixes * remove test that is tested via yaml anyway * Only include required parameters or non-empty optional parameters in URLs, support oneOf/anyOf via nim object variants, optional field support * snapshot * docs gen * Improved handling of enums
1 parent 65f99eb commit 4a7e0c9

38 files changed

+1804
-97
lines changed

docs/generators/nim.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,8 +226,8 @@ These options may be applied as additional-properties (cli) or configOptions (pl
226226
|Polymorphism|✗|OAS2,OAS3
227227
|Union|✗|OAS3
228228
|allOf|✗|OAS2,OAS3
229-
|anyOf||OAS3
230-
|oneOf||OAS3
229+
|anyOf||OAS3
230+
|oneOf||OAS3
231231
|not|✗|OAS3
232232

233233
### Security Feature

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/NimClientCodegen.java

Lines changed: 364 additions & 7 deletions
Large diffs are not rendered by default.

modules/openapi-generator/src/main/resources/nim-client/api.mustache

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,7 @@ const basepath = "{{{basePath}}}"
1818
template constructResult[T](response: Response): untyped =
1919
if response.code in {Http200, Http201, Http202, Http204, Http206}:
2020
try:
21-
when name(stripGenericParams(T.typedesc).typedesc) == name(Table):
22-
(some(json.to(parseJson(response.body), T.typedesc)), response)
23-
else:
24-
(some(marshal.to[T](response.body)), response)
21+
(some(to(parseJson(response.body), T)), response)
2522
except JsonParsingError:
2623
# The server returned a malformed response though the response code is 2XX
2724
# TODO: need better error handling
@@ -37,19 +34,27 @@ proc {{{operationId}}}*(httpClient: HttpClient{{#allParams}}, {{{paramName}}}: {
3734
httpClient.headers["Content-Type"] = "application/x-www-form-urlencoded"{{/isMultipart}}{{#isMultipart}}
3835
httpClient.headers["Content-Type"] = "multipart/form-data"{{/isMultipart}}{{/hasFormParams}}{{#hasHeaderParams}}{{#headerParams}}
3936
httpClient.headers["{{{baseName}}}"] = {{{paramName}}}{{#isArray}}.join(","){{/isArray}}{{/headerParams}}{{#description}} ## {{{.}}}{{/description}}{{/hasHeaderParams}}{{#hasQueryParams}}
40-
let url_encoded_query_params = encodeQuery([{{#queryParams}}
41-
("{{{baseName}}}", ${{{paramName}}}{{#isArray}}.join(","){{/isArray}}), # {{{description}}}{{/queryParams}}
42-
]){{/hasQueryParams}}{{#hasFormParams}}{{^isMultipart}}
37+
var query_params_list: seq[(string, string)] = @[]{{#queryParams}}{{#required}}
38+
query_params_list.add(("{{{baseName}}}", ${{{paramName}}}{{#isArray}}.join(","){{/isArray}})){{/required}}{{^required}}
39+
if {{#isArray}}{{{paramName}}}.len > 0{{/isArray}}{{^isArray}}${{{paramName}}} != ""{{/isArray}}:
40+
query_params_list.add(("{{{baseName}}}", ${{{paramName}}}{{#isArray}}.join(","){{/isArray}})){{/required}}{{/queryParams}}
41+
let url_encoded_query_params = encodeQuery(query_params_list){{/hasQueryParams}}{{#hasFormParams}}{{^isMultipart}}
4342
let form_data = encodeQuery([{{#formParams}}
4443
("{{{baseName}}}", ${{{paramName}}}{{#isArray}}.join(","){{/isArray}}), # {{{description}}}{{/formParams}}
4544
]){{/isMultipart}}{{#isMultipart}}
4645
let multipart_data = newMultipartData({
4746
{{#formParams}} "{{{baseName}}}": ${{{paramName}}}{{#isArray}}.join(","){{/isArray}}, # {{{description}}}
4847
{{/formParams}}
4948
}){{/isMultipart}}{{/hasFormParams}}{{#returnType}}
50-
49+
{{#vendorExtensions.x-nim-delete-with-body}}
50+
let response = httpClient.request(basepath & {{^pathParams}}"{{{path}}}"{{/pathParams}}{{#hasPathParams}}fmt"{{{path}}}"{{/hasPathParams}}{{#hasQueryParams}} & "?" & url_encoded_query_params{{/hasQueryParams}}, httpMethod = HttpDelete{{#bodyParams}}, body = $(%{{{paramName}}}){{/bodyParams}})
51+
{{/vendorExtensions.x-nim-delete-with-body}}{{^vendorExtensions.x-nim-delete-with-body}}
5152
let response = httpClient.{{{httpMethod}}}(basepath & {{^pathParams}}"{{{path}}}"{{/pathParams}}{{#hasPathParams}}fmt"{{{path}}}"{{/hasPathParams}}{{#hasQueryParams}} & "?" & url_encoded_query_params{{/hasQueryParams}}{{#hasBodyParam}}{{#bodyParams}}, $(%{{{paramName}}}){{/bodyParams}}{{/hasBodyParam}}{{#hasFormParams}}, {{^isMultipart}}$form_data{{/isMultipart}}{{#isMultipart}}multipart=multipart_data{{/isMultipart}}{{/hasFormParams}})
52-
constructResult[{{{returnType}}}](response){{/returnType}}{{^returnType}}
53-
httpClient.{{{httpMethod}}}(basepath & {{^pathParams}}"{{{path}}}"{{/pathParams}}{{#hasPathParams}}fmt"{{{path}}}"{{/hasPathParams}}{{#hasQueryParams}} & "?" & url_encoded_query_params{{/hasQueryParams}}{{#hasBodyParam}}{{#bodyParams}}, $(%{{{paramName}}}){{/bodyParams}}{{/hasBodyParam}}{{#hasFormParams}}, {{^isMultipart}}$form_data{{/isMultipart}}{{#isMultipart}}multipart=multipart_data{{/isMultipart}}{{/hasFormParams}}){{/returnType}}
53+
{{/vendorExtensions.x-nim-delete-with-body}}
54+
constructResult[{{{returnType}}}](response){{/returnType}}{{^returnType}}{{#vendorExtensions.x-nim-delete-with-body}}
55+
httpClient.request(basepath & {{^pathParams}}"{{{path}}}"{{/pathParams}}{{#hasPathParams}}fmt"{{{path}}}"{{/hasPathParams}}{{#hasQueryParams}} & "?" & url_encoded_query_params{{/hasQueryParams}}, httpMethod = HttpDelete{{#bodyParams}}, body = $(%{{{paramName}}}){{/bodyParams}})
56+
{{/vendorExtensions.x-nim-delete-with-body}}{{^vendorExtensions.x-nim-delete-with-body}}
57+
httpClient.{{{httpMethod}}}(basepath & {{^pathParams}}"{{{path}}}"{{/pathParams}}{{#hasPathParams}}fmt"{{{path}}}"{{/hasPathParams}}{{#hasQueryParams}} & "?" & url_encoded_query_params{{/hasQueryParams}}{{#hasBodyParam}}{{#bodyParams}}, $(%{{{paramName}}}){{/bodyParams}}{{/hasBodyParam}}{{#hasFormParams}}, {{^isMultipart}}$form_data{{/isMultipart}}{{#isMultipart}}multipart=multipart_data{{/isMultipart}}{{/hasFormParams}})
58+
{{/vendorExtensions.x-nim-delete-with-body}}{{/returnType}}
5459

5560
{{/operation}}{{/operations}}
Lines changed: 171 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,184 @@
11
{{>header}}
22
import json
33
import tables
4+
import marshal
5+
import options
46

57
{{#imports}}import {{import}}
6-
{{/imports}}{{#models}}{{#model}}{{#vars}}{{#isEnum}}
8+
{{/imports}}{{#models}}{{#model}}{{#isEnum}}
9+
type {{{classname}}}* {.pure.} = enum{{#allowableValues}}{{#enumVars}}
10+
{{{name}}}{{/enumVars}}{{/allowableValues}}
11+
12+
{{#vendorExtensions.x-is-integer-enum}}
13+
func `%`*(v: {{{classname}}}): JsonNode =
14+
result = case v:{{#allowableValues}}{{#enumVars}}
15+
of {{{classname}}}.{{{name}}}: %({{{value}}}){{/enumVars}}{{/allowableValues}}
16+
17+
{{/vendorExtensions.x-is-integer-enum}}
18+
{{^vendorExtensions.x-is-integer-enum}}
19+
func `%`*(v: {{{classname}}}): JsonNode =
20+
result = case v:{{#allowableValues}}{{#enumVars}}
21+
of {{{classname}}}.{{{name}}}: %{{{value}}}{{/enumVars}}{{/allowableValues}}
22+
23+
{{/vendorExtensions.x-is-integer-enum}}
24+
func `$`*(v: {{{classname}}}): string =
25+
result = case v:{{#allowableValues}}{{#enumVars}}
26+
of {{{classname}}}.{{{name}}}: $({{{value}}}){{/enumVars}}{{/allowableValues}}
27+
{{#vendorExtensions.x-is-integer-enum}}
28+
proc to*(node: JsonNode, T: typedesc[{{{classname}}}]): {{{classname}}} =
29+
if node.kind != JInt:
30+
raise newException(ValueError, "Expected integer for enum {{{classname}}}, got " & $node.kind)
31+
let intVal = node.getInt()
32+
case intVal:{{#allowableValues}}{{#enumVars}}
33+
of {{{value}}}:
34+
return {{{classname}}}.{{{name}}}{{/enumVars}}{{/allowableValues}}
35+
else:
36+
raise newException(ValueError, "Invalid enum value for {{{classname}}}: " & $intVal)
37+
{{/vendorExtensions.x-is-integer-enum}}{{^vendorExtensions.x-is-integer-enum}}
38+
proc to*(node: JsonNode, T: typedesc[{{{classname}}}]): {{{classname}}} =
39+
if node.kind != JString:
40+
raise newException(ValueError, "Expected string for enum {{{classname}}}, got " & $node.kind)
41+
let strVal = node.getStr()
42+
case strVal:{{#allowableValues}}{{#enumVars}}
43+
of $({{{value}}}):
44+
return {{{classname}}}.{{{name}}}{{/enumVars}}{{/allowableValues}}
45+
else:
46+
raise newException(ValueError, "Invalid enum value for {{{classname}}}: " & strVal)
47+
{{/vendorExtensions.x-is-integer-enum}}
48+
{{/isEnum}}{{^isEnum}}{{#vendorExtensions.x-is-one-of}}
49+
# OneOf type
50+
type {{{classname}}}Kind* {.pure.} = enum{{#composedSchemas.oneOf}}
51+
{{{name}}}Variant{{/composedSchemas.oneOf}}
52+
53+
type {{{classname}}}* = object
54+
## {{{description}}}
55+
case kind*: {{{classname}}}Kind{{#composedSchemas.oneOf}}
56+
of {{{classname}}}Kind.{{{name}}}Variant:
57+
{{{baseName}}}Value*: {{{dataType}}}{{/composedSchemas.oneOf}}
58+
59+
proc to*(node: JsonNode, T: typedesc[{{{classname}}}]): {{{classname}}} =
60+
## Custom deserializer for oneOf type - tries each variant{{#composedSchemas.oneOf}}
61+
try:
62+
return {{{classname}}}(kind: {{{classname}}}Kind.{{{name}}}Variant, {{{baseName}}}Value: to(node, {{{dataType}}}))
63+
except Exception as e:
64+
when defined(debug):
65+
echo "Failed to deserialize as {{{dataType}}}: ", e.msg{{/composedSchemas.oneOf}}
66+
raise newException(ValueError, "Unable to deserialize into any variant of {{{classname}}}. JSON: " & $node)
67+
{{/vendorExtensions.x-is-one-of}}{{#vendorExtensions.x-is-any-of}}
68+
# AnyOf type
69+
type {{{classname}}}Kind* {.pure.} = enum{{#composedSchemas.anyOf}}
70+
{{{name}}}Variant{{/composedSchemas.anyOf}}
71+
72+
type {{{classname}}}* = object
73+
## {{{description}}}
74+
case kind*: {{{classname}}}Kind{{#composedSchemas.anyOf}}
75+
of {{{classname}}}Kind.{{{name}}}Variant:
76+
{{{baseName}}}Value*: {{{dataType}}}{{/composedSchemas.anyOf}}
77+
78+
proc to*(node: JsonNode, T: typedesc[{{{classname}}}]): {{{classname}}} =
79+
## Custom deserializer for anyOf type - tries each variant{{#composedSchemas.anyOf}}
80+
try:
81+
return {{{classname}}}(kind: {{{classname}}}Kind.{{{name}}}Variant, {{{baseName}}}Value: to(node, {{{dataType}}}))
82+
except Exception as e:
83+
when defined(debug):
84+
echo "Failed to deserialize as {{{dataType}}}: ", e.msg{{/composedSchemas.anyOf}}
85+
raise newException(ValueError, "Unable to deserialize into any variant of {{{classname}}}. JSON: " & $node)
86+
{{/vendorExtensions.x-is-any-of}}{{^vendorExtensions.x-is-one-of}}{{^vendorExtensions.x-is-any-of}}{{#vars}}{{#isEnum}}
787
type {{{enumName}}}* {.pure.} = enum{{#allowableValues}}{{#enumVars}}
888
{{{name}}}{{/enumVars}}{{/allowableValues}}
989
{{/isEnum}}{{/vars}}
1090
type {{{classname}}}* = object
1191
## {{{description}}}{{#vars}}
12-
{{{name}}}*: {{#isEnum}}{{{enumName}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{#description}} ## {{{.}}}{{/description}}{{/vars}}
13-
{{#vars}}{{#isEnum}}
92+
{{{name}}}*: {{#isEnum}}{{#vendorExtensions.x-is-optional}}Option[{{{enumName}}}]{{/vendorExtensions.x-is-optional}}{{^vendorExtensions.x-is-optional}}{{{enumName}}}{{/vendorExtensions.x-is-optional}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{#description}} ## {{{.}}}{{/description}}{{/vars}}
93+
{{#vars}}{{#isEnum}}{{#vendorExtensions.x-is-integer-enum}}
1494
func `%`*(v: {{{enumName}}}): JsonNode =
15-
let str = case v:{{#allowableValues}}{{#enumVars}}
16-
of {{{enumName}}}.{{{name}}}: {{{value}}}{{/enumVars}}{{/allowableValues}}
17-
18-
JsonNode(kind: JString, str: str)
19-
95+
result = case v:{{#allowableValues}}{{#enumVars}}
96+
of {{{enumName}}}.{{{name}}}: %({{{value}}}){{/enumVars}}{{/allowableValues}}
97+
{{/vendorExtensions.x-is-integer-enum}}{{^vendorExtensions.x-is-integer-enum}}
98+
func `%`*(v: {{{enumName}}}): JsonNode =
99+
result = case v:{{#allowableValues}}{{#enumVars}}
100+
of {{{enumName}}}.{{{name}}}: %{{{value}}}{{/enumVars}}{{/allowableValues}}
101+
{{/vendorExtensions.x-is-integer-enum}}
20102
func `$`*(v: {{{enumName}}}): string =
21103
result = case v:{{#allowableValues}}{{#enumVars}}
22-
of {{{enumName}}}.{{{name}}}: {{{value}}}{{/enumVars}}{{/allowableValues}}
23-
{{/isEnum}}{{/vars}}{{/model}}{{/models}}
104+
of {{{enumName}}}.{{{name}}}: $({{{value}}}){{/enumVars}}{{/allowableValues}}
105+
{{#vendorExtensions.x-is-integer-enum}}
106+
proc to*(node: JsonNode, T: typedesc[{{{enumName}}}]): {{{enumName}}} =
107+
if node.kind != JInt:
108+
raise newException(ValueError, "Expected integer for enum {{{enumName}}}, got " & $node.kind)
109+
let intVal = node.getInt()
110+
case intVal:{{#allowableValues}}{{#enumVars}}
111+
of {{{value}}}:
112+
return {{{enumName}}}.{{{name}}}{{/enumVars}}{{/allowableValues}}
113+
else:
114+
raise newException(ValueError, "Invalid enum value for {{{enumName}}}: " & $intVal)
115+
{{/vendorExtensions.x-is-integer-enum}}{{^vendorExtensions.x-is-integer-enum}}
116+
proc to*(node: JsonNode, T: typedesc[{{{enumName}}}]): {{{enumName}}} =
117+
if node.kind != JString:
118+
raise newException(ValueError, "Expected string for enum {{{enumName}}}, got " & $node.kind)
119+
let strVal = node.getStr()
120+
case strVal:{{#allowableValues}}{{#enumVars}}
121+
of $({{{value}}}):
122+
return {{{enumName}}}.{{{name}}}{{/enumVars}}{{/allowableValues}}
123+
else:
124+
raise newException(ValueError, "Invalid enum value for {{{enumName}}}: " & strVal)
125+
{{/vendorExtensions.x-is-integer-enum}}
126+
{{/isEnum}}{{/vars}}{{#vendorExtensions.x-has-custom-json-names}}
127+
128+
# Custom JSON deserialization for {{{classname}}} with custom field names
129+
proc to*(node: JsonNode, T: typedesc[{{{classname}}}]): {{{classname}}} =
130+
result = {{{classname}}}()
131+
if node.kind == JObject:{{#vars}}{{#vendorExtensions.x-json-name}}{{#vendorExtensions.x-is-optional}}
132+
if node.hasKey("{{{vendorExtensions.x-json-name}}}") and node["{{{vendorExtensions.x-json-name}}}"].kind != JNull:{{#vendorExtensions.x-is-array-with-custom-json}}
133+
# Optional array of types with custom JSON - manually iterate and deserialize
134+
let arrayNode = node["{{{vendorExtensions.x-json-name}}}"]
135+
if arrayNode.kind == JArray:
136+
var arr: seq[{{{vendorExtensions.x-array-inner-type}}}] = @[]
137+
for item in arrayNode.items:
138+
arr.add(to(item, {{{vendorExtensions.x-array-inner-type}}}))
139+
result.{{{name}}} = some(arr){{/vendorExtensions.x-is-array-with-custom-json}}{{^vendorExtensions.x-is-array-with-custom-json}}{{#vendorExtensions.x-is-external-enum}}
140+
result.{{{name}}} = some({{{vendorExtensions.x-enum-module}}}.to(node["{{{vendorExtensions.x-json-name}}}"], {{{vendorExtensions.x-enum-type}}})){{/vendorExtensions.x-is-external-enum}}{{^vendorExtensions.x-is-external-enum}}{{#isEnum}}
141+
result.{{{name}}} = some(to(node["{{{vendorExtensions.x-json-name}}}"], {{{enumName}}})){{/isEnum}}{{^isEnum}}
142+
result.{{{name}}} = some(to(node["{{{vendorExtensions.x-json-name}}}"], typeof(result.{{{name}}}.get()))){{/isEnum}}{{/vendorExtensions.x-is-external-enum}}{{/vendorExtensions.x-is-array-with-custom-json}}{{/vendorExtensions.x-is-optional}}{{^vendorExtensions.x-is-optional}}
143+
if node.hasKey("{{{vendorExtensions.x-json-name}}}"):{{#vendorExtensions.x-is-array-with-custom-json}}
144+
# Array of types with custom JSON - manually iterate and deserialize
145+
let arrayNode = node["{{{vendorExtensions.x-json-name}}}"]
146+
if arrayNode.kind == JArray:
147+
result.{{{name}}} = @[]
148+
for item in arrayNode.items:
149+
result.{{{name}}}.add(to(item, {{{vendorExtensions.x-array-inner-type}}})){{/vendorExtensions.x-is-array-with-custom-json}}{{^vendorExtensions.x-is-array-with-custom-json}}{{#vendorExtensions.x-is-external-enum}}
150+
result.{{{name}}} = {{{vendorExtensions.x-enum-module}}}.to(node["{{{vendorExtensions.x-json-name}}}"], {{{vendorExtensions.x-enum-type}}}){{/vendorExtensions.x-is-external-enum}}{{^vendorExtensions.x-is-external-enum}}{{#isEnum}}
151+
result.{{{name}}} = to(node["{{{vendorExtensions.x-json-name}}}"], {{{enumName}}}){{/isEnum}}{{^isEnum}}
152+
result.{{{name}}} = to(node["{{{vendorExtensions.x-json-name}}}"], {{{dataType}}}){{/isEnum}}{{/vendorExtensions.x-is-external-enum}}{{/vendorExtensions.x-is-array-with-custom-json}}{{/vendorExtensions.x-is-optional}}{{/vendorExtensions.x-json-name}}{{^vendorExtensions.x-json-name}}{{#vendorExtensions.x-is-optional}}
153+
if node.hasKey("{{{baseName}}}") and node["{{{baseName}}}"].kind != JNull:{{#vendorExtensions.x-is-array-with-custom-json}}
154+
# Optional array of types with custom JSON - manually iterate and deserialize
155+
let arrayNode = node["{{{baseName}}}"]
156+
if arrayNode.kind == JArray:
157+
var arr: seq[{{{vendorExtensions.x-array-inner-type}}}] = @[]
158+
for item in arrayNode.items:
159+
arr.add(to(item, {{{vendorExtensions.x-array-inner-type}}}))
160+
result.{{{name}}} = some(arr){{/vendorExtensions.x-is-array-with-custom-json}}{{^vendorExtensions.x-is-array-with-custom-json}}{{#vendorExtensions.x-is-external-enum}}
161+
result.{{{name}}} = some({{{vendorExtensions.x-enum-module}}}.to(node["{{{baseName}}}"], {{{vendorExtensions.x-enum-type}}})){{/vendorExtensions.x-is-external-enum}}{{^vendorExtensions.x-is-external-enum}}{{#isEnum}}
162+
result.{{{name}}} = some(to(node["{{{baseName}}}"], {{{enumName}}})){{/isEnum}}{{^isEnum}}
163+
result.{{{name}}} = some(to(node["{{{baseName}}}"], typeof(result.{{{name}}}.get()))){{/isEnum}}{{/vendorExtensions.x-is-external-enum}}{{/vendorExtensions.x-is-array-with-custom-json}}{{/vendorExtensions.x-is-optional}}{{^vendorExtensions.x-is-optional}}
164+
if node.hasKey("{{{baseName}}}"):{{#vendorExtensions.x-is-array-with-custom-json}}
165+
# Array of types with custom JSON - manually iterate and deserialize
166+
let arrayNode = node["{{{baseName}}}"]
167+
if arrayNode.kind == JArray:
168+
result.{{{name}}} = @[]
169+
for item in arrayNode.items:
170+
result.{{{name}}}.add(to(item, {{{vendorExtensions.x-array-inner-type}}})){{/vendorExtensions.x-is-array-with-custom-json}}{{^vendorExtensions.x-is-array-with-custom-json}}{{#vendorExtensions.x-is-external-enum}}
171+
result.{{{name}}} = {{{vendorExtensions.x-enum-module}}}.to(node["{{{baseName}}}"], {{{vendorExtensions.x-enum-type}}}){{/vendorExtensions.x-is-external-enum}}{{^vendorExtensions.x-is-external-enum}}{{#isEnum}}
172+
result.{{{name}}} = to(node["{{{baseName}}}"], {{{enumName}}}){{/isEnum}}{{^isEnum}}
173+
result.{{{name}}} = to(node["{{{baseName}}}"], {{{dataType}}}){{/isEnum}}{{/vendorExtensions.x-is-external-enum}}{{/vendorExtensions.x-is-array-with-custom-json}}{{/vendorExtensions.x-is-optional}}{{/vendorExtensions.x-json-name}}{{/vars}}
174+
175+
# Custom JSON serialization for {{{classname}}} with custom field names
176+
proc `%`*(obj: {{{classname}}}): JsonNode =
177+
result = newJObject(){{#vars}}{{#vendorExtensions.x-json-name}}{{#vendorExtensions.x-is-optional}}
178+
if obj.{{{name}}}.isSome():
179+
result["{{{vendorExtensions.x-json-name}}}"] = %obj.{{{name}}}.get(){{/vendorExtensions.x-is-optional}}{{^vendorExtensions.x-is-optional}}
180+
result["{{{vendorExtensions.x-json-name}}}"] = %obj.{{{name}}}{{/vendorExtensions.x-is-optional}}{{/vendorExtensions.x-json-name}}{{^vendorExtensions.x-json-name}}{{#vendorExtensions.x-is-optional}}
181+
if obj.{{{name}}}.isSome():
182+
result["{{{baseName}}}"] = %obj.{{{name}}}.get(){{/vendorExtensions.x-is-optional}}{{^vendorExtensions.x-is-optional}}
183+
result["{{{baseName}}}"] = %obj.{{{name}}}{{/vendorExtensions.x-is-optional}}{{/vendorExtensions.x-json-name}}{{/vars}}
184+
{{/vendorExtensions.x-has-custom-json-names}}{{/vendorExtensions.x-is-any-of}}{{/vendorExtensions.x-is-one-of}}{{/isEnum}}{{/model}}{{/models}}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{{>header}}
2+
import json
3+
4+
# AnyType represents any JSON value
5+
# This is used for fields that can contain arbitrary JSON data
6+
type AnyType* = JsonNode
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{{>header}}
2+
import json
3+
import tables
4+
5+
# Object represents an arbitrary JSON object
6+
# Using JsonNode instead of the 'object' keyword to avoid Nim keyword conflicts
7+
type Object* = JsonNode

0 commit comments

Comments
 (0)