quicktype-core 6.1.12 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -29,7 +29,7 @@ export { removeNullFromUnion, matchType, nullableFromUnion } from "./TypeUtils";
29
29
  export { ConvenienceRenderer } from "./ConvenienceRenderer";
30
30
  export { uriTypeAttributeKind } from "./attributes/URIAttributes";
31
31
  export { CPlusPlusTargetLanguage, CPlusPlusRenderer, cPlusPlusOptions } from "./language/CPlusPlus";
32
- export { CSharpTargetLanguage, cSharpOptions, CSharpRenderer, NewtonsoftCSharpTargetLanguage, newtonsoftCSharpOptions, NewtonsoftCSharpRenderer } from "./language/CSharp";
32
+ export { CSharpTargetLanguage, cSharpOptions, CSharpRenderer } from "./language/CSharp";
33
33
  export { GoTargetLanguage, GoRenderer, goOptions } from "./language/Golang";
34
34
  export { ObjectiveCTargetLanguage, ObjectiveCRenderer, objcOptions } from "./language/Objective-C";
35
35
  export { JavaTargetLanguage, JavaRenderer, javaOptions } from "./language/Java";
package/dist/index.js CHANGED
@@ -111,9 +111,6 @@ var CSharp_1 = require("./language/CSharp");
111
111
  exports.CSharpTargetLanguage = CSharp_1.CSharpTargetLanguage;
112
112
  exports.cSharpOptions = CSharp_1.cSharpOptions;
113
113
  exports.CSharpRenderer = CSharp_1.CSharpRenderer;
114
- exports.NewtonsoftCSharpTargetLanguage = CSharp_1.NewtonsoftCSharpTargetLanguage;
115
- exports.newtonsoftCSharpOptions = CSharp_1.newtonsoftCSharpOptions;
116
- exports.NewtonsoftCSharpRenderer = CSharp_1.NewtonsoftCSharpRenderer;
117
114
  var Golang_1 = require("./language/Golang");
118
115
  exports.GoTargetLanguage = Golang_1.GoTargetLanguage;
119
116
  exports.GoRenderer = Golang_1.GoRenderer;
@@ -21,7 +21,7 @@ const Python_1 = require("./Python");
21
21
  const Pike_1 = require("./Pike");
22
22
  const Haskell_1 = require("./Haskell");
23
23
  exports.all = [
24
- new CSharp_1.NewtonsoftCSharpTargetLanguage(),
24
+ new CSharp_1.CSharpTargetLanguage(),
25
25
  new Golang_1.GoTargetLanguage(),
26
26
  new Rust_1.RustTargetLanguage(),
27
27
  new Crystal_1.CrystalTargetLanguage(),
@@ -7,6 +7,10 @@ import { StringOption, EnumOption, Option, BooleanOption, OptionValues } from ".
7
7
  import { StringTypeMapping } from "../TypeBuilder";
8
8
  import { Transformation } from "../Transformers";
9
9
  import { RenderContext } from "../Renderer";
10
+ export declare enum Framework {
11
+ Newtonsoft = 0,
12
+ SystemTextJson = 1
13
+ }
10
14
  export declare type Version = 5 | 6;
11
15
  export declare type OutputFeatures = {
12
16
  helpers: boolean;
@@ -19,6 +23,7 @@ export declare enum AccessModifier {
19
23
  }
20
24
  export declare type CSharpTypeForAny = "object" | "dynamic";
21
25
  export declare const cSharpOptions: {
26
+ framework: EnumOption<Framework>;
22
27
  useList: EnumOption<boolean>;
23
28
  dense: EnumOption<boolean>;
24
29
  namespace: StringOption;
@@ -28,6 +33,7 @@ export declare const cSharpOptions: {
28
33
  useDecimal: EnumOption<boolean>;
29
34
  };
30
35
  export declare class CSharpTargetLanguage extends TargetLanguage {
36
+ constructor();
31
37
  protected getOptions(): Option<any>[];
32
38
  readonly stringTypeMapping: StringTypeMapping;
33
39
  readonly supportsUnionsWithBothNumberTypes: boolean;
@@ -35,7 +41,7 @@ export declare class CSharpTargetLanguage extends TargetLanguage {
35
41
  needsTransformerForType(t: Type): boolean;
36
42
  protected makeRenderer(renderContext: RenderContext, untypedOptionValues: {
37
43
  [name: string]: any;
38
- }): CSharpRenderer;
44
+ }): ConvenienceRenderer;
39
45
  }
40
46
  export declare class CSharpRenderer extends ConvenienceRenderer {
41
47
  private readonly _csOptions;
@@ -69,10 +75,12 @@ export declare class CSharpRenderer extends ConvenienceRenderer {
69
75
  protected emitRequiredHelpers(): void;
70
76
  private emitTypesAndSupport;
71
77
  protected emitDefaultLeadingComments(): void;
78
+ protected emitDefaultFollowingComments(): void;
72
79
  protected needNamespace(): boolean;
73
80
  protected emitSourceStructure(): void;
74
81
  }
75
82
  export declare const newtonsoftCSharpOptions: {
83
+ framework: EnumOption<Framework>;
76
84
  useList: EnumOption<boolean>;
77
85
  dense: EnumOption<boolean>;
78
86
  namespace: StringOption;
@@ -89,13 +97,6 @@ export declare const newtonsoftCSharpOptions: {
89
97
  baseclass: EnumOption<string | undefined>;
90
98
  checkRequired: BooleanOption;
91
99
  };
92
- export declare class NewtonsoftCSharpTargetLanguage extends CSharpTargetLanguage {
93
- constructor();
94
- protected getOptions(): Option<any>[];
95
- protected makeRenderer(renderContext: RenderContext, untypedOptionValues: {
96
- [name: string]: any;
97
- }): NewtonsoftCSharpRenderer;
98
- }
99
100
  export declare class NewtonsoftCSharpRenderer extends CSharpRenderer {
100
101
  private readonly _options;
101
102
  private readonly _enumExtensionsNames;
@@ -135,3 +136,61 @@ export declare class NewtonsoftCSharpRenderer extends CSharpRenderer {
135
136
  protected emitRequiredHelpers(): void;
136
137
  protected needNamespace(): boolean;
137
138
  }
139
+ export declare const systemTextJsonCSharpOptions: {
140
+ framework: EnumOption<Framework>;
141
+ useList: EnumOption<boolean>;
142
+ dense: EnumOption<boolean>;
143
+ namespace: StringOption;
144
+ version: EnumOption<Version>;
145
+ virtual: BooleanOption;
146
+ typeForAny: EnumOption<CSharpTypeForAny>;
147
+ useDecimal: EnumOption<boolean>;
148
+ } & {
149
+ features: EnumOption<{
150
+ namespaces: boolean;
151
+ helpers: boolean;
152
+ attributes: boolean;
153
+ }>;
154
+ baseclass: EnumOption<string | undefined>;
155
+ checkRequired: BooleanOption;
156
+ };
157
+ export declare class SystemTextJsonCSharpRenderer extends CSharpRenderer {
158
+ private readonly _options;
159
+ private readonly _enumExtensionsNames;
160
+ private readonly _needHelpers;
161
+ private readonly _needAttributes;
162
+ private readonly _needNamespaces;
163
+ constructor(targetLanguage: TargetLanguage, renderContext: RenderContext, _options: OptionValues<typeof systemTextJsonCSharpOptions>);
164
+ protected forbiddenNamesForGlobalNamespace(): string[];
165
+ protected forbiddenForObjectProperties(c: ClassType, className: Name): ForbiddenWordsInfo;
166
+ protected makeNameForTransformation(xf: Transformation, typeName: Name | undefined): Name;
167
+ protected makeNamedTypeDependencyNames(t: Type, name: Name): DependencyName[];
168
+ protected emitUsings(): void;
169
+ protected baseclassForType(_t: Type): Sourcelike | undefined;
170
+ protected emitDefaultFollowingComments(): void;
171
+ protected emitDefaultLeadingComments(): void;
172
+ private converterForType;
173
+ protected attributesForProperty(property: ClassProperty, _name: Name, _c: ClassType, jsonName: string): Sourcelike[] | undefined;
174
+ protected blankLinesBetweenAttributes(): boolean;
175
+ private topLevelResultType;
176
+ private emitFromJsonForTopLevel;
177
+ private emitDecoderSwitch;
178
+ private emitTokenCase;
179
+ private emitThrow;
180
+ private deserializeTypeCode;
181
+ private serializeValueCode;
182
+ private emitSerializeClass;
183
+ private emitCanConvert;
184
+ private emitReadJson;
185
+ private emitWriteJson;
186
+ private converterObject;
187
+ private emitConverterClass;
188
+ private emitDecoderTransformerCase;
189
+ private emitConsume;
190
+ private emitDecodeTransformer;
191
+ private stringCaseValue;
192
+ private emitTransformer;
193
+ private emitTransformation;
194
+ protected emitRequiredHelpers(): void;
195
+ protected needNamespace(): boolean;
196
+ }
@@ -13,6 +13,11 @@ const RendererOptions_1 = require("../RendererOptions");
13
13
  const Annotation_1 = require("../Annotation");
14
14
  const Transformers_1 = require("../Transformers");
15
15
  const Constraints_1 = require("../attributes/Constraints");
16
+ var Framework;
17
+ (function (Framework) {
18
+ Framework[Framework["Newtonsoft"] = 0] = "Newtonsoft";
19
+ Framework[Framework["SystemTextJson"] = 1] = "SystemTextJson";
20
+ })(Framework = exports.Framework || (exports.Framework = {}));
16
21
  const unicode = require("@mark.probst/unicode-properties");
17
22
  var AccessModifier;
18
23
  (function (AccessModifier) {
@@ -73,6 +78,7 @@ function csTypeForTransformedStringType(t) {
73
78
  }
74
79
  }
75
80
  exports.cSharpOptions = {
81
+ framework: new RendererOptions_1.EnumOption("framework", "Serialization framework", [["NewtonSoft", Framework.Newtonsoft], ["SystemTextJson", Framework.SystemTextJson]], "NewtonSoft"),
76
82
  useList: new RendererOptions_1.EnumOption("array-type", "Use T[] or List<T>", [
77
83
  ["array", false],
78
84
  ["list", true],
@@ -98,8 +104,12 @@ exports.cSharpOptions = {
98
104
  ], "double", "secondary"),
99
105
  };
100
106
  class CSharpTargetLanguage extends TargetLanguage_1.TargetLanguage {
107
+ constructor() {
108
+ super("C#", ["cs", "csharp"], "cs");
109
+ }
101
110
  getOptions() {
102
111
  return [
112
+ exports.cSharpOptions.framework,
103
113
  exports.cSharpOptions.namespace,
104
114
  exports.cSharpOptions.version,
105
115
  exports.cSharpOptions.dense,
@@ -131,7 +141,15 @@ class CSharpTargetLanguage extends TargetLanguage_1.TargetLanguage {
131
141
  return need !== "none" && need !== "nullable";
132
142
  }
133
143
  makeRenderer(renderContext, untypedOptionValues) {
134
- return new CSharpRenderer(this, renderContext, RendererOptions_1.getOptionValues(exports.cSharpOptions, untypedOptionValues));
144
+ const options = RendererOptions_1.getOptionValues(exports.cSharpOptions, untypedOptionValues);
145
+ switch (options.framework) {
146
+ case Framework.Newtonsoft:
147
+ return new NewtonsoftCSharpRenderer(this, renderContext, RendererOptions_1.getOptionValues(exports.newtonsoftCSharpOptions, untypedOptionValues));
148
+ case Framework.SystemTextJson:
149
+ return new SystemTextJsonCSharpRenderer(this, renderContext, RendererOptions_1.getOptionValues(exports.systemTextJsonCSharpOptions, untypedOptionValues));
150
+ default:
151
+ return Support_1.assertNever(options.framework);
152
+ }
135
153
  }
136
154
  }
137
155
  exports.CSharpTargetLanguage = CSharpTargetLanguage;
@@ -423,6 +441,9 @@ class CSharpRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
423
441
  emitDefaultLeadingComments() {
424
442
  return;
425
443
  }
444
+ emitDefaultFollowingComments() {
445
+ return;
446
+ }
426
447
  needNamespace() {
427
448
  return true;
428
449
  }
@@ -445,6 +466,7 @@ class CSharpRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
445
466
  this.emitUsings();
446
467
  this.emitTypesAndSupport();
447
468
  }
469
+ this.emitDefaultFollowingComments();
448
470
  }
449
471
  }
450
472
  exports.CSharpRenderer = CSharpRenderer;
@@ -461,29 +483,6 @@ exports.newtonsoftCSharpOptions = Object.assign({}, exports.cSharpOptions, {
461
483
  ], "Object", "secondary"),
462
484
  checkRequired: new RendererOptions_1.BooleanOption("check-required", "Fail if required properties are missing", false),
463
485
  });
464
- class NewtonsoftCSharpTargetLanguage extends CSharpTargetLanguage {
465
- constructor() {
466
- super("C#", ["cs", "csharp"], "cs");
467
- }
468
- getOptions() {
469
- return [
470
- exports.newtonsoftCSharpOptions.namespace,
471
- exports.newtonsoftCSharpOptions.version,
472
- exports.newtonsoftCSharpOptions.dense,
473
- exports.newtonsoftCSharpOptions.useList,
474
- exports.newtonsoftCSharpOptions.useDecimal,
475
- exports.newtonsoftCSharpOptions.features,
476
- exports.newtonsoftCSharpOptions.checkRequired,
477
- exports.newtonsoftCSharpOptions.typeForAny,
478
- exports.newtonsoftCSharpOptions.baseclass,
479
- exports.newtonsoftCSharpOptions.virtual,
480
- ];
481
- }
482
- makeRenderer(renderContext, untypedOptionValues) {
483
- return new NewtonsoftCSharpRenderer(this, renderContext, RendererOptions_1.getOptionValues(exports.newtonsoftCSharpOptions, untypedOptionValues));
484
- }
485
- }
486
- exports.NewtonsoftCSharpTargetLanguage = NewtonsoftCSharpTargetLanguage;
487
486
  class NewtonsoftCSharpRenderer extends CSharpRenderer {
488
487
  constructor(targetLanguage, renderContext, _options) {
489
488
  super(targetLanguage, renderContext, _options);
@@ -1080,3 +1079,765 @@ class NewtonsoftCSharpRenderer extends CSharpRenderer {
1080
1079
  }
1081
1080
  }
1082
1081
  exports.NewtonsoftCSharpRenderer = NewtonsoftCSharpRenderer;
1082
+ exports.systemTextJsonCSharpOptions = Object.assign({}, exports.cSharpOptions, {
1083
+ features: new RendererOptions_1.EnumOption("features", "Output features", [
1084
+ ["complete", { namespaces: true, helpers: true, attributes: true }],
1085
+ ["attributes-only", { namespaces: true, helpers: false, attributes: true }],
1086
+ ["just-types-and-namespace", { namespaces: true, helpers: false, attributes: false }],
1087
+ ["just-types", { namespaces: true, helpers: false, attributes: false }],
1088
+ ]),
1089
+ baseclass: new RendererOptions_1.EnumOption("base-class", "Base class", [
1090
+ ["EntityData", "EntityData"],
1091
+ ["Object", undefined],
1092
+ ], "Object", "secondary"),
1093
+ checkRequired: new RendererOptions_1.BooleanOption("check-required", "Fail if required properties are missing", false),
1094
+ });
1095
+ class SystemTextJsonCSharpRenderer extends CSharpRenderer {
1096
+ constructor(targetLanguage, renderContext, _options) {
1097
+ super(targetLanguage, renderContext, _options);
1098
+ this._options = _options;
1099
+ this._enumExtensionsNames = new Map();
1100
+ this._needHelpers = _options.features.helpers;
1101
+ this._needAttributes = _options.features.attributes;
1102
+ this._needNamespaces = _options.features.namespaces;
1103
+ }
1104
+ forbiddenNamesForGlobalNamespace() {
1105
+ const forbidden = [
1106
+ "Converter",
1107
+ "JsonConverter",
1108
+ "JsonSerializer",
1109
+ "JsonWriter",
1110
+ "JsonToken",
1111
+ "Serialize",
1112
+ "JsonSerializerOptions",
1113
+ // "Newtonsoft",
1114
+ // "MetadataPropertyHandling",
1115
+ // "DateParseHandling",
1116
+ "FromJson",
1117
+ "Required"
1118
+ ];
1119
+ if (this._options.dense) {
1120
+ forbidden.push("J", "R", "N");
1121
+ }
1122
+ if (this._options.baseclass !== undefined) {
1123
+ forbidden.push(this._options.baseclass);
1124
+ }
1125
+ return super.forbiddenNamesForGlobalNamespace().concat(forbidden);
1126
+ }
1127
+ forbiddenForObjectProperties(c, className) {
1128
+ const result = super.forbiddenForObjectProperties(c, className);
1129
+ result.names = result.names.concat(["ToJson", "FromJson", "Required"]);
1130
+ return result;
1131
+ }
1132
+ makeNameForTransformation(xf, typeName) {
1133
+ if (typeName === undefined) {
1134
+ let xfer = xf.transformer;
1135
+ if (xfer instanceof Transformers_1.DecodingTransformer && xfer.consumer !== undefined) {
1136
+ xfer = xfer.consumer;
1137
+ }
1138
+ return new Naming_1.SimpleName([`${xfer.kind}_converter`], namingFunction, ConvenienceRenderer_1.inferredNameOrder + 30);
1139
+ }
1140
+ return new Naming_1.DependencyName(namingFunction, typeName.order + 30, lookup => `${lookup(typeName)}_converter`);
1141
+ }
1142
+ makeNamedTypeDependencyNames(t, name) {
1143
+ if (!(t instanceof Type_1.EnumType))
1144
+ return [];
1145
+ const extensionsName = new Naming_1.DependencyName(namingFunction, name.order + 30, lookup => `${lookup(name)}_extensions`);
1146
+ this._enumExtensionsNames.set(name, extensionsName);
1147
+ return [extensionsName];
1148
+ }
1149
+ emitUsings() {
1150
+ // FIXME: We need System.Collections.Generic whenever we have maps or use List.
1151
+ if (!this._needAttributes && !this._needHelpers)
1152
+ return;
1153
+ super.emitUsings();
1154
+ this.ensureBlankLine();
1155
+ for (const ns of ["System.Text.Json", "System.Text.Json.Serialization", "System.Globalization"]) {
1156
+ this.emitUsing(ns);
1157
+ }
1158
+ if (this._options.dense) {
1159
+ this.emitUsing([denseJsonPropertyName, " = System.Text.Json.Serialization.JsonPropertyNameAttribute"]);
1160
+ // this.emitUsing([denseRequiredEnumName, " = Newtonsoft.Json.Required"]);
1161
+ this.emitUsing([denseNullValueHandlingEnumName, " = System.Text.Json.Serialization.JsonIgnoreCondition"]);
1162
+ }
1163
+ if (this._options.baseclass === "EntityData") {
1164
+ this.emitUsing("Microsoft.Azure.Mobile.Server");
1165
+ }
1166
+ }
1167
+ baseclassForType(_t) {
1168
+ return this._options.baseclass;
1169
+ }
1170
+ emitDefaultFollowingComments() {
1171
+ if (!this._needHelpers)
1172
+ return;
1173
+ this.emitLine("#pragma warning restore CS8618");
1174
+ this.emitLine("#pragma warning restore CS8601");
1175
+ this.emitLine("#pragma warning restore CS8603");
1176
+ }
1177
+ emitDefaultLeadingComments() {
1178
+ if (!this._needHelpers)
1179
+ return;
1180
+ this.emitLine("// <auto-generated />");
1181
+ this.emitLine("//");
1182
+ this.emitLine("// To parse this JSON data, add NuGet 'System.Text.Json' then do", this.topLevels.size === 1 ? "" : " one of these", ":");
1183
+ this.emitLine("//");
1184
+ this.emitLine("// using ", this._options.namespace, ";");
1185
+ this.emitLine("//");
1186
+ this.forEachTopLevel("none", (t, topLevelName) => {
1187
+ let rhs;
1188
+ if (t instanceof Type_1.EnumType) {
1189
+ rhs = ["JsonSerializer.Deserialize<", topLevelName, ">(jsonString)"];
1190
+ }
1191
+ else {
1192
+ rhs = [topLevelName, ".FromJson(jsonString)"];
1193
+ }
1194
+ this.emitLine("// var ", Source_1.modifySource(Strings_1.camelCase, topLevelName), " = ", rhs, ";");
1195
+ });
1196
+ // fix: should this be an option? Or respond to an existing option?
1197
+ this.emitLine("#nullable enable");
1198
+ this.emitLine("#pragma warning disable CS8618");
1199
+ this.emitLine("#pragma warning disable CS8601");
1200
+ this.emitLine("#pragma warning disable CS8603");
1201
+ }
1202
+ converterForType(t) {
1203
+ let xf = Transformers_1.transformationForType(t);
1204
+ if (xf === undefined && t instanceof Type_1.UnionType) {
1205
+ const maybeNullable = TypeUtils_1.nullableFromUnion(t);
1206
+ if (maybeNullable !== null) {
1207
+ t = maybeNullable;
1208
+ xf = Transformers_1.transformationForType(t);
1209
+ }
1210
+ }
1211
+ if (xf === undefined)
1212
+ return undefined;
1213
+ if (alwaysApplyTransformation(xf))
1214
+ return undefined;
1215
+ return Support_1.defined(this.nameForTransformation(t));
1216
+ }
1217
+ attributesForProperty(property, _name, _c, jsonName) {
1218
+ if (!this._needAttributes)
1219
+ return undefined;
1220
+ const attributes = [];
1221
+ const jsonPropertyName = this._options.dense ? denseJsonPropertyName : "JsonPropertyName";
1222
+ const escapedName = Strings_1.utf16StringEscape(jsonName);
1223
+ const isNullable = Transformers_1.followTargetType(property.type).isNullable;
1224
+ const isOptional = property.isOptional;
1225
+ if (isOptional && !isNullable) {
1226
+ attributes.push(["[", "JsonIgnore", "(Condition = JsonIgnoreCondition.WhenWritingNull)]"]);
1227
+ }
1228
+ // const requiredClass = this._options.dense ? "R" : "Required";
1229
+ // const nullValueHandlingClass = this._options.dense ? "N" : "NullValueHandling";
1230
+ // const nullValueHandling = isOptional && !isNullable ? [", NullValueHandling = ", nullValueHandlingClass, ".Ignore"] : [];
1231
+ // let required: Sourcelike;
1232
+ // if (!this._options.checkRequired || (isOptional && isNullable)) {
1233
+ // required = [nullValueHandling];
1234
+ // } else if (isOptional && !isNullable) {
1235
+ // required = [", Required = ", requiredClass, ".DisallowNull", nullValueHandling];
1236
+ // } else if (!isOptional && isNullable) {
1237
+ // required = [", Required = ", requiredClass, ".AllowNull"];
1238
+ // } else {
1239
+ // required = [", Required = ", requiredClass, ".Always", nullValueHandling];
1240
+ // }
1241
+ attributes.push(["[", jsonPropertyName, '("', escapedName, '")]']);
1242
+ const converter = this.converterForType(property.type);
1243
+ if (converter !== undefined) {
1244
+ attributes.push(["[JsonConverter(typeof(", converter, "))]"]);
1245
+ }
1246
+ return attributes;
1247
+ }
1248
+ blankLinesBetweenAttributes() {
1249
+ return this._needAttributes && !this._options.dense;
1250
+ }
1251
+ // The "this" type can't be `dynamic`, so we have to force it to `object`.
1252
+ topLevelResultType(t) {
1253
+ return t.kind === "any" || t.kind === "none" ? "object" : this.csType(t);
1254
+ }
1255
+ emitFromJsonForTopLevel(t, name) {
1256
+ if (t instanceof Type_1.EnumType)
1257
+ return;
1258
+ let partial;
1259
+ let typeKind;
1260
+ const definedType = this.namedTypeToNameForTopLevel(t);
1261
+ if (definedType !== undefined) {
1262
+ partial = "partial ";
1263
+ typeKind = definedType instanceof Type_1.ClassType ? "class" : "struct";
1264
+ }
1265
+ else {
1266
+ partial = "";
1267
+ typeKind = "class";
1268
+ }
1269
+ const csType = this.topLevelResultType(t);
1270
+ this.emitType(undefined, AccessModifier.Public, [partial, typeKind], name, this.baseclassForType(t), () => {
1271
+ // FIXME: Make FromJson a Named
1272
+ this.emitExpressionMember(["public static ", csType, " FromJson(string json)"], ["JsonSerializer.Deserialize<", csType, ">(json, ", this._options.namespace, ".Converter.Settings)"]);
1273
+ });
1274
+ }
1275
+ emitDecoderSwitch(emitBody) {
1276
+ this.emitLine("switch (reader.TokenType)");
1277
+ this.emitBlock(emitBody);
1278
+ }
1279
+ emitTokenCase(tokenType) {
1280
+ this.emitLine("case JsonTokenType.", tokenType, ":");
1281
+ }
1282
+ emitThrow(message) {
1283
+ this.emitLine("throw new Exception(", message, ");");
1284
+ }
1285
+ deserializeTypeCode(typeName) {
1286
+ switch (typeName) {
1287
+ case "bool":
1288
+ return ["reader.GetBoolean()"];
1289
+ case "long":
1290
+ return ["reader.GetInt64()"];
1291
+ case "decimal":
1292
+ return ["reader.GetDecimal()"];
1293
+ case "double":
1294
+ return ["reader.GetDouble()"];
1295
+ case "string":
1296
+ return ["reader.GetString()"];
1297
+ default:
1298
+ return ["JsonSerializer.Deserialize<", typeName, ">(ref reader, options)"];
1299
+ }
1300
+ }
1301
+ serializeValueCode(value) {
1302
+ if (value !== "null")
1303
+ return ["JsonSerializer.Serialize(writer, ", value, ", options)"];
1304
+ else
1305
+ return ["writer.WriteNullValue()"];
1306
+ }
1307
+ emitSerializeClass() {
1308
+ // FIXME: Make Serialize a Named
1309
+ this.emitType(undefined, AccessModifier.Public, "static class", "Serialize", undefined, () => {
1310
+ // Sometimes multiple top-levels will resolve to the same type, so we have to take care
1311
+ // not to emit more than one extension method for the same type.
1312
+ const seenTypes = new Set();
1313
+ this.forEachTopLevel("none", t => {
1314
+ // FIXME: Make ToJson a Named
1315
+ if (!seenTypes.has(t)) {
1316
+ seenTypes.add(t);
1317
+ this.emitExpressionMember(["public static string ToJson(this ", this.topLevelResultType(t), " self)"], ["JsonSerializer.Serialize(self, ", this._options.namespace, ".Converter.Settings)"]);
1318
+ }
1319
+ });
1320
+ });
1321
+ }
1322
+ emitCanConvert(expr) {
1323
+ this.emitExpressionMember("public override bool CanConvert(Type t)", expr);
1324
+ }
1325
+ emitReadJson(emitBody, csType) {
1326
+ this.emitLine("public override ", csType, " Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)");
1327
+ this.emitBlock(emitBody);
1328
+ }
1329
+ emitWriteJson(variable, emitBody, csType) {
1330
+ this.emitLine("public override void Write(Utf8JsonWriter writer, ", csType, " ", variable, ", JsonSerializerOptions options)");
1331
+ this.emitBlock(emitBody);
1332
+ }
1333
+ converterObject(converterName) {
1334
+ // FIXME: Get a singleton
1335
+ return [converterName, ".Singleton"];
1336
+ }
1337
+ emitConverterClass() {
1338
+ // FIXME: Make Converter a Named
1339
+ const converterName = ["Converter"];
1340
+ this.emitType(undefined, AccessModifier.Internal, "static class", converterName, undefined, () => {
1341
+ // Do not use .Web as defaults. That turns on caseInsensitive property names and will fail the keywords test.
1342
+ this.emitLine("public static readonly JsonSerializerOptions Settings = new(JsonSerializerDefaults.General)");
1343
+ this.emitBlock(() => {
1344
+ // this.emitLine("MetadataPropertyHandling = MetadataPropertyHandling.Ignore,");
1345
+ // this.emitLine("DateParseHandling = DateParseHandling.None,");
1346
+ this.emitLine("Converters =");
1347
+ this.emitLine("{");
1348
+ this.indent(() => {
1349
+ for (const [t, converter] of this.typesWithNamedTransformations) {
1350
+ if (alwaysApplyTransformation(Support_1.defined(Transformers_1.transformationForType(t)))) {
1351
+ this.emitLine(this.converterObject(converter), ",");
1352
+ }
1353
+ }
1354
+ this.emitLine("new DateOnlyConverter(),");
1355
+ this.emitLine("new TimeOnlyConverter(),");
1356
+ this.emitLine("IsoDateTimeOffsetConverter.Singleton");
1357
+ // this.emitLine("new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }");
1358
+ });
1359
+ this.emitLine(`},`);
1360
+ }, true);
1361
+ });
1362
+ }
1363
+ emitDecoderTransformerCase(tokenCases, variableName, xfer, targetType, emitFinish) {
1364
+ if (xfer === undefined)
1365
+ return;
1366
+ for (const tokenCase of tokenCases) {
1367
+ this.emitTokenCase(tokenCase);
1368
+ }
1369
+ this.indent(() => {
1370
+ const allHandled = this.emitDecodeTransformer(xfer, targetType, emitFinish, variableName);
1371
+ if (!allHandled) {
1372
+ this.emitLine("break;");
1373
+ }
1374
+ });
1375
+ }
1376
+ emitConsume(value, consumer, targetType, emitFinish) {
1377
+ if (consumer === undefined) {
1378
+ emitFinish(value);
1379
+ return true;
1380
+ }
1381
+ else {
1382
+ return this.emitTransformer(value, consumer, targetType, emitFinish);
1383
+ }
1384
+ }
1385
+ emitDecodeTransformer(xfer, targetType, emitFinish, variableName = "value") {
1386
+ if (xfer instanceof Transformers_1.DecodingTransformer) {
1387
+ const source = xfer.sourceType;
1388
+ const converter = this.converterForType(targetType);
1389
+ if (converter !== undefined) {
1390
+ const typeSource = this.csType(targetType);
1391
+ this.emitLine("var converter = ", this.converterObject(converter), ";");
1392
+ this.emitLine("var ", variableName, " = (", typeSource, ")converter.ReadJson(reader, typeof(", typeSource, "), null, serializer);");
1393
+ }
1394
+ else if (source.kind !== "null") {
1395
+ let output = targetType.kind === "double" ? targetType : source;
1396
+ this.emitLine("var ", variableName, " = ", this.deserializeTypeCode(this.csType(output)), ";");
1397
+ }
1398
+ return this.emitConsume(variableName, xfer.consumer, targetType, emitFinish);
1399
+ }
1400
+ else if (xfer instanceof Transformers_1.ArrayDecodingTransformer) {
1401
+ // FIXME: Consume StartArray
1402
+ if (!(targetType instanceof Type_1.ArrayType)) {
1403
+ return Support_1.panic("Array decoding must produce an array type");
1404
+ }
1405
+ // FIXME: handle EOF
1406
+ this.emitLine("reader.Read();");
1407
+ this.emitLine("var ", variableName, " = new List<", this.csType(targetType.items), ">();");
1408
+ this.emitLine("while (reader.TokenType != JsonToken.EndArray)");
1409
+ this.emitBlock(() => {
1410
+ this.emitDecodeTransformer(xfer.itemTransformer, xfer.itemTargetType, v => this.emitLine(variableName, ".Add(", v, ");"), "arrayItem");
1411
+ // FIXME: handle EOF
1412
+ this.emitLine("reader.Read();");
1413
+ });
1414
+ let result = variableName;
1415
+ if (!this._options.useList) {
1416
+ result = [result, ".ToArray()"];
1417
+ }
1418
+ emitFinish(result);
1419
+ return true;
1420
+ }
1421
+ else if (xfer instanceof Transformers_1.DecodingChoiceTransformer) {
1422
+ this.emitDecoderSwitch(() => {
1423
+ const nullTransformer = xfer.nullTransformer;
1424
+ if (nullTransformer !== undefined) {
1425
+ this.emitTokenCase("Null");
1426
+ this.indent(() => {
1427
+ const allHandled = this.emitDecodeTransformer(nullTransformer, targetType, emitFinish, "null");
1428
+ if (!allHandled) {
1429
+ this.emitLine("break");
1430
+ }
1431
+ });
1432
+ }
1433
+ this.emitDecoderTransformerCase(["Number"], "integerValue", xfer.integerTransformer, targetType, emitFinish);
1434
+ this.emitDecoderTransformerCase(["Number"],
1435
+ // xfer.integerTransformer === undefined ? ["Integer", "Float"] : ["Float"],
1436
+ "doubleValue", xfer.doubleTransformer, targetType, emitFinish);
1437
+ this.emitDecoderTransformerCase(["True", "False"], "boolValue", xfer.boolTransformer, targetType, emitFinish);
1438
+ this.emitDecoderTransformerCase(
1439
+ // ["String", "Date"],
1440
+ ["String"], "stringValue", xfer.stringTransformer, targetType, emitFinish);
1441
+ this.emitDecoderTransformerCase(["StartObject"], "objectValue", xfer.objectTransformer, targetType, emitFinish);
1442
+ this.emitDecoderTransformerCase(["StartArray"], "arrayValue", xfer.arrayTransformer, targetType, emitFinish);
1443
+ });
1444
+ return false;
1445
+ }
1446
+ else {
1447
+ return Support_1.panic("Unknown transformer");
1448
+ }
1449
+ }
1450
+ stringCaseValue(t, stringCase) {
1451
+ if (t.kind === "string") {
1452
+ return ['"', Strings_1.utf16StringEscape(stringCase), '"'];
1453
+ }
1454
+ else if (t instanceof Type_1.EnumType) {
1455
+ return [this.nameForNamedType(t), ".", this.nameForEnumCase(t, stringCase)];
1456
+ }
1457
+ return Support_1.panic(`Type ${t.kind} does not have string cases`);
1458
+ }
1459
+ emitTransformer(variable, xfer, targetType, emitFinish) {
1460
+ function directTargetType(continuation) {
1461
+ if (continuation === undefined) {
1462
+ return targetType;
1463
+ }
1464
+ return Transformers_1.followTargetType(continuation.sourceType);
1465
+ }
1466
+ if (xfer instanceof Transformers_1.ChoiceTransformer) {
1467
+ const caseXfers = xfer.transformers;
1468
+ if (caseXfers.length > 1 && caseXfers.every(caseXfer => caseXfer instanceof Transformers_1.StringMatchTransformer)) {
1469
+ this.emitLine("switch (", variable, ")");
1470
+ this.emitBlock(() => {
1471
+ for (const caseXfer of caseXfers) {
1472
+ const matchXfer = caseXfer;
1473
+ const value = this.stringCaseValue(Transformers_1.followTargetType(matchXfer.sourceType), matchXfer.stringCase);
1474
+ this.emitLine("case ", value, ":");
1475
+ this.indent(() => {
1476
+ const allDone = this.emitTransformer(variable, matchXfer.transformer, targetType, emitFinish);
1477
+ if (!allDone) {
1478
+ this.emitLine("break;");
1479
+ }
1480
+ });
1481
+ }
1482
+ });
1483
+ // FIXME: Can we check for exhaustiveness? For enums it should be easy.
1484
+ return false;
1485
+ }
1486
+ else {
1487
+ for (const caseXfer of caseXfers) {
1488
+ this.emitTransformer(variable, caseXfer, targetType, emitFinish);
1489
+ }
1490
+ }
1491
+ }
1492
+ else if (xfer instanceof Transformers_1.UnionMemberMatchTransformer) {
1493
+ const memberType = xfer.memberType;
1494
+ const maybeNullable = TypeUtils_1.nullableFromUnion(xfer.sourceType);
1495
+ let test;
1496
+ let member;
1497
+ if (maybeNullable !== null) {
1498
+ if (memberType.kind === "null") {
1499
+ test = [variable, " == null"];
1500
+ member = "null";
1501
+ }
1502
+ else {
1503
+ test = [variable, " != null"];
1504
+ member = variable;
1505
+ }
1506
+ }
1507
+ else if (memberType.kind === "null") {
1508
+ test = [variable, ".IsNull"];
1509
+ member = "null";
1510
+ }
1511
+ else {
1512
+ const memberName = this.nameForUnionMember(xfer.sourceType, memberType);
1513
+ member = [variable, ".", memberName];
1514
+ test = [member, " != null"];
1515
+ }
1516
+ if (memberType.kind !== "null" && isValueType(memberType)) {
1517
+ member = [member, ".Value"];
1518
+ }
1519
+ this.emitLine("if (", test, ")");
1520
+ this.emitBlock(() => this.emitTransformer(member, xfer.transformer, targetType, emitFinish));
1521
+ }
1522
+ else if (xfer instanceof Transformers_1.StringMatchTransformer) {
1523
+ const value = this.stringCaseValue(Transformers_1.followTargetType(xfer.sourceType), xfer.stringCase);
1524
+ this.emitLine("if (", variable, " == ", value, ")");
1525
+ this.emitBlock(() => this.emitTransformer(variable, xfer.transformer, targetType, emitFinish));
1526
+ }
1527
+ else if (xfer instanceof Transformers_1.EncodingTransformer) {
1528
+ const converter = this.converterForType(xfer.sourceType);
1529
+ if (converter !== undefined) {
1530
+ this.emitLine("var converter = ", this.converterObject(converter), ";");
1531
+ this.emitLine("converter.WriteJson(writer, ", variable, ", serializer);");
1532
+ }
1533
+ else {
1534
+ this.emitLine(this.serializeValueCode(variable), ";");
1535
+ }
1536
+ emitFinish([]);
1537
+ return true;
1538
+ }
1539
+ else if (xfer instanceof Transformers_1.ArrayEncodingTransformer) {
1540
+ this.emitLine("writer.WriteStartArray();");
1541
+ const itemVariable = "arrayItem";
1542
+ this.emitLine("foreach (var ", itemVariable, " in ", variable, ")");
1543
+ this.emitBlock(() => {
1544
+ this.emitTransformer(itemVariable, xfer.itemTransformer, xfer.itemTargetType, () => {
1545
+ return;
1546
+ });
1547
+ });
1548
+ this.emitLine("writer.WriteEndArray();");
1549
+ emitFinish([]);
1550
+ return true;
1551
+ }
1552
+ else if (xfer instanceof Transformers_1.ParseStringTransformer) {
1553
+ const immediateTargetType = xfer.consumer === undefined ? targetType : xfer.consumer.sourceType;
1554
+ switch (immediateTargetType.kind) {
1555
+ case "date-time":
1556
+ this.emitLine("DateTimeOffset dt;");
1557
+ this.emitLine("if (DateTimeOffset.TryParse(", variable, ", out dt))");
1558
+ this.emitBlock(() => this.emitConsume("dt", xfer.consumer, targetType, emitFinish));
1559
+ break;
1560
+ case "uuid":
1561
+ this.emitLine("Guid guid;");
1562
+ this.emitLine("if (Guid.TryParse(", variable, ", out guid))");
1563
+ this.emitBlock(() => this.emitConsume("guid", xfer.consumer, targetType, emitFinish));
1564
+ break;
1565
+ case "uri":
1566
+ this.emitLine("try");
1567
+ this.emitBlock(() => {
1568
+ // this.emitLine("var uri = new Uri(", variable, ");");
1569
+ // The default value about:blank should never happen, but this way we avoid a null reference warning.
1570
+ this.emitLine("var uri = new Uri(\"about:blank\");");
1571
+ this.emitLine("if (!string.IsNullOrEmpty(stringValue))");
1572
+ this.emitBlock(() => {
1573
+ this.emitLine("uri = new Uri(", variable, ");");
1574
+ });
1575
+ this.emitConsume("uri", xfer.consumer, targetType, emitFinish);
1576
+ });
1577
+ this.emitLine("catch (UriFormatException) {}");
1578
+ break;
1579
+ case "integer":
1580
+ this.emitLine("long l;");
1581
+ this.emitLine("if (Int64.TryParse(", variable, ", out l))");
1582
+ this.emitBlock(() => this.emitConsume("l", xfer.consumer, targetType, emitFinish));
1583
+ break;
1584
+ case "bool":
1585
+ this.emitLine("bool b;");
1586
+ this.emitLine("if (Boolean.TryParse(", variable, ", out b))");
1587
+ this.emitBlock(() => this.emitConsume("b", xfer.consumer, targetType, emitFinish));
1588
+ break;
1589
+ default:
1590
+ return Support_1.panic(`Parsing string to ${immediateTargetType.kind} not supported`);
1591
+ }
1592
+ }
1593
+ else if (xfer instanceof Transformers_1.StringifyTransformer) {
1594
+ switch (xfer.sourceType.kind) {
1595
+ case "date-time":
1596
+ return this.emitConsume([variable, '.ToString("o", System.Globalization.CultureInfo.InvariantCulture)'], xfer.consumer, targetType, emitFinish);
1597
+ case "uuid":
1598
+ return this.emitConsume([variable, '.ToString("D", System.Globalization.CultureInfo.InvariantCulture)'], xfer.consumer, targetType, emitFinish);
1599
+ case "integer":
1600
+ case "uri":
1601
+ return this.emitConsume([variable, ".ToString()"], xfer.consumer, targetType, emitFinish);
1602
+ case "bool":
1603
+ this.emitLine("var boolString = ", variable, ' ? "true" : "false";');
1604
+ return this.emitConsume("boolString", xfer.consumer, targetType, emitFinish);
1605
+ default:
1606
+ return Support_1.panic(`Stringifying ${xfer.sourceType.kind} not supported`);
1607
+ }
1608
+ }
1609
+ else if (xfer instanceof Transformers_1.StringProducerTransformer) {
1610
+ const value = this.stringCaseValue(directTargetType(xfer.consumer), xfer.result);
1611
+ return this.emitConsume(value, xfer.consumer, targetType, emitFinish);
1612
+ }
1613
+ else if (xfer instanceof Transformers_1.MinMaxLengthCheckTransformer) {
1614
+ const min = xfer.minLength;
1615
+ const max = xfer.maxLength;
1616
+ const conditions = [];
1617
+ if (min !== undefined) {
1618
+ conditions.push([variable, ".Length >= ", min.toString()]);
1619
+ }
1620
+ if (max !== undefined) {
1621
+ conditions.push([variable, ".Length <= ", max.toString()]);
1622
+ }
1623
+ this.emitLine("if (", collection_utils_1.arrayIntercalate([" && "], conditions), ")");
1624
+ this.emitBlock(() => this.emitConsume(variable, xfer.consumer, targetType, emitFinish));
1625
+ return false;
1626
+ }
1627
+ else if (xfer instanceof Transformers_1.MinMaxValueTransformer) {
1628
+ const min = xfer.minimum;
1629
+ const max = xfer.maximum;
1630
+ const conditions = [];
1631
+ if (min !== undefined) {
1632
+ conditions.push([variable, " >= ", min.toString()]);
1633
+ }
1634
+ if (max !== undefined) {
1635
+ conditions.push([variable, " <= ", max.toString()]);
1636
+ }
1637
+ this.emitLine("if (", collection_utils_1.arrayIntercalate([" && "], conditions), ")");
1638
+ this.emitBlock(() => this.emitConsume(variable, xfer.consumer, targetType, emitFinish));
1639
+ return false;
1640
+ }
1641
+ else if (xfer instanceof Transformers_1.UnionInstantiationTransformer) {
1642
+ if (!(targetType instanceof Type_1.UnionType)) {
1643
+ return Support_1.panic("Union instantiation transformer must produce a union type");
1644
+ }
1645
+ const maybeNullable = TypeUtils_1.nullableFromUnion(targetType);
1646
+ if (maybeNullable !== null) {
1647
+ emitFinish(variable);
1648
+ }
1649
+ else {
1650
+ const unionName = this.nameForNamedType(targetType);
1651
+ let initializer;
1652
+ if (xfer.sourceType.kind === "null") {
1653
+ initializer = " ";
1654
+ }
1655
+ else {
1656
+ const memberName = this.nameForUnionMember(targetType, xfer.sourceType);
1657
+ initializer = [" ", memberName, " = ", variable, " "];
1658
+ }
1659
+ emitFinish(["new ", unionName, " {", initializer, "}"]);
1660
+ }
1661
+ return true;
1662
+ }
1663
+ else {
1664
+ return Support_1.panic("Unknown transformer");
1665
+ }
1666
+ return false;
1667
+ }
1668
+ emitTransformation(converterName, t) {
1669
+ const xf = Support_1.defined(Transformers_1.transformationForType(t));
1670
+ const reverse = xf.reverse;
1671
+ const targetType = xf.targetType;
1672
+ const xfer = xf.transformer;
1673
+ const csType = this.csType(targetType);
1674
+ // const haveNullable = isValueType(targetType);
1675
+ // if (haveNullable) {
1676
+ // converterName = ['Nullable', converterName];
1677
+ // csType = [csType, "?"];
1678
+ // }
1679
+ this.emitType(undefined, AccessModifier.Internal, "class", converterName, ["JsonConverter<", csType, ">"], () => {
1680
+ let canConvertExpr = ["t == typeof(", csType, ")"];
1681
+ this.emitCanConvert(canConvertExpr);
1682
+ this.ensureBlankLine();
1683
+ this.emitReadJson(() => {
1684
+ // FIXME: It's unsatisfying that we need this. The reason is that we not
1685
+ // only match T, but also T?. If we didn't, then the T in T? would not be
1686
+ // deserialized with our converter but with the default one. Can we check
1687
+ // whether the type is a nullable?
1688
+ // FIXME: This could duplicate one of the cases handled below in
1689
+ // `emitDecodeTransformer`.
1690
+ // if (haveNullable && !(targetType instanceof UnionType)) {
1691
+ // this.emitLine("if (reader.TokenType == JsonTokenType.Null) return null;");
1692
+ // }
1693
+ const allHandled = this.emitDecodeTransformer(xfer, targetType, v => this.emitLine("return ", v, ";"));
1694
+ if (!allHandled) {
1695
+ this.emitThrow(['"Cannot unmarshal type ', csType, '"']);
1696
+ }
1697
+ }, csType);
1698
+ this.ensureBlankLine();
1699
+ this.emitWriteJson("value", () => {
1700
+ // FIXME: See above.
1701
+ // if (haveNullable && !(targetType instanceof UnionType)) {
1702
+ // this.emitLine("if (value == null)");
1703
+ // this.emitBlock(() => {
1704
+ // this.emitLine("writer.WriteNullValue();");
1705
+ // this.emitLine("return;");
1706
+ // });
1707
+ // }
1708
+ const allHandled = this.emitTransformer("value", reverse.transformer, reverse.targetType, () => this.emitLine("return;"));
1709
+ if (!allHandled) {
1710
+ this.emitThrow(['"Cannot marshal type ', csType, '"']);
1711
+ }
1712
+ }, csType);
1713
+ this.ensureBlankLine();
1714
+ this.emitLine("public static readonly ", converterName, " Singleton = new ", converterName, "();");
1715
+ });
1716
+ }
1717
+ emitRequiredHelpers() {
1718
+ if (this._needHelpers) {
1719
+ this.forEachTopLevel("leading-and-interposing", (t, n) => this.emitFromJsonForTopLevel(t, n));
1720
+ this.ensureBlankLine();
1721
+ this.emitSerializeClass();
1722
+ }
1723
+ if (this._needHelpers || (this._needAttributes && (this.haveNamedUnions || this.haveEnums))) {
1724
+ this.ensureBlankLine();
1725
+ this.emitConverterClass();
1726
+ this.forEachTransformation("leading-and-interposing", (n, t) => this.emitTransformation(n, t));
1727
+ this.emitMultiline(`
1728
+ public class DateOnlyConverter : JsonConverter<DateOnly>
1729
+ {
1730
+ private readonly string serializationFormat;
1731
+ public DateOnlyConverter() : this(null) { }
1732
+
1733
+ public DateOnlyConverter(string? serializationFormat)
1734
+ {
1735
+ this.serializationFormat = serializationFormat ?? "yyyy-MM-dd";
1736
+ }
1737
+
1738
+ public override DateOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
1739
+ {
1740
+ var value = reader.GetString();
1741
+ return DateOnly.Parse(value!);
1742
+ }
1743
+
1744
+ public override void Write(Utf8JsonWriter writer, DateOnly value, JsonSerializerOptions options)
1745
+ => writer.WriteStringValue(value.ToString(serializationFormat));
1746
+ }
1747
+
1748
+ public class TimeOnlyConverter : JsonConverter<TimeOnly>
1749
+ {
1750
+ private readonly string serializationFormat;
1751
+
1752
+ public TimeOnlyConverter() : this(null) { }
1753
+
1754
+ public TimeOnlyConverter(string? serializationFormat)
1755
+ {
1756
+ this.serializationFormat = serializationFormat ?? "HH:mm:ss.fff";
1757
+ }
1758
+
1759
+ public override TimeOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
1760
+ {
1761
+ var value = reader.GetString();
1762
+ return TimeOnly.Parse(value!);
1763
+ }
1764
+
1765
+ public override void Write(Utf8JsonWriter writer, TimeOnly value, JsonSerializerOptions options)
1766
+ => writer.WriteStringValue(value.ToString(serializationFormat));
1767
+ }
1768
+
1769
+ internal class IsoDateTimeOffsetConverter : JsonConverter<DateTimeOffset>
1770
+ {
1771
+ public override bool CanConvert(Type t) => t == typeof(DateTimeOffset);
1772
+
1773
+ private const string DefaultDateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK";
1774
+
1775
+ private DateTimeStyles _dateTimeStyles = DateTimeStyles.RoundtripKind;
1776
+ private string? _dateTimeFormat;
1777
+ private CultureInfo? _culture;
1778
+
1779
+ public DateTimeStyles DateTimeStyles
1780
+ {
1781
+ get => _dateTimeStyles;
1782
+ set => _dateTimeStyles = value;
1783
+ }
1784
+
1785
+ public string? DateTimeFormat
1786
+ {
1787
+ get => _dateTimeFormat ?? string.Empty;
1788
+ set => _dateTimeFormat = (string.IsNullOrEmpty(value)) ? null : value;
1789
+ }
1790
+
1791
+ public CultureInfo Culture
1792
+ {
1793
+ get => _culture ?? CultureInfo.CurrentCulture;
1794
+ set => _culture = value;
1795
+ }
1796
+
1797
+ public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options)
1798
+ {
1799
+ string text;
1800
+
1801
+
1802
+ if ((_dateTimeStyles & DateTimeStyles.AdjustToUniversal) == DateTimeStyles.AdjustToUniversal
1803
+ || (_dateTimeStyles & DateTimeStyles.AssumeUniversal) == DateTimeStyles.AssumeUniversal)
1804
+ {
1805
+ value = value.ToUniversalTime();
1806
+ }
1807
+
1808
+ text = value.ToString(_dateTimeFormat ?? DefaultDateTimeFormat, Culture);
1809
+
1810
+ writer.WriteStringValue(text);
1811
+ }
1812
+
1813
+ public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
1814
+ {
1815
+ string? dateText = reader.GetString();
1816
+
1817
+ if (string.IsNullOrEmpty(dateText) == false)
1818
+ {
1819
+ if (!string.IsNullOrEmpty(_dateTimeFormat))
1820
+ {
1821
+ return DateTimeOffset.ParseExact(dateText, _dateTimeFormat, Culture, _dateTimeStyles);
1822
+ }
1823
+ else
1824
+ {
1825
+ return DateTimeOffset.Parse(dateText, Culture, _dateTimeStyles);
1826
+ }
1827
+ }
1828
+ else
1829
+ {
1830
+ return default(DateTimeOffset);
1831
+ }
1832
+ }
1833
+
1834
+
1835
+ public static readonly IsoDateTimeOffsetConverter Singleton = new IsoDateTimeOffsetConverter();
1836
+ }`);
1837
+ }
1838
+ }
1839
+ needNamespace() {
1840
+ return this._needNamespaces;
1841
+ }
1842
+ }
1843
+ exports.SystemTextJsonCSharpRenderer = SystemTextJsonCSharpRenderer;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quicktype-core",
3
- "version": "6.1.12",
3
+ "version": "7.0.0",
4
4
  "description": "The quicktype engine as a library",
5
5
  "license": "Apache-2.0",
6
6
  "main": "dist/index.js",
@@ -45,6 +45,6 @@
45
45
  "fs": false
46
46
  },
47
47
  "config": {
48
- "commit": "7d5b0ce40ada9c206b0808709a6f219051424d98"
48
+ "commit": "3118cbe3f215406f704558a1e5e07e5160b5fcff"
49
49
  }
50
50
  }