quicktype-core 20.0.26 → 21.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.
@@ -120,12 +120,22 @@ export declare class CPlusPlusRenderer extends ConvenienceRenderer {
120
120
  private readonly _memberNamingFunction;
121
121
  private _stringType;
122
122
  private _optionalType;
123
+ private _optionalFactory;
123
124
  private _nulloptType;
124
125
  private _variantType;
125
126
  private _variantIndexMethodName;
126
127
  protected readonly typeNamingStyle: NamingStyle;
127
128
  protected readonly enumeratorNamingStyle: NamingStyle;
128
129
  constructor(targetLanguage: TargetLanguage, renderContext: RenderContext, _options: OptionValues<typeof cPlusPlusOptions>);
130
+ isUnion(t: Type | UnionType): t is UnionType;
131
+ isOptionalAsValuePossible(t: Type): boolean;
132
+ isImplicitCycleBreaker(t: Type): boolean;
133
+ optionalTypeStack(): string;
134
+ optionalFactoryStack(): string;
135
+ optionalTypeHeap(): string;
136
+ optionalFactoryHeap(): string;
137
+ optionalType(t: Type): string;
138
+ optionalTypeLabel(t: Type): string;
129
139
  protected getConstraintMembers(): ConstraintMember[];
130
140
  protected lookupGlobalName(type: GlobalNames): string;
131
141
  protected lookupMemberName(type: MemberNames): string;
@@ -154,7 +164,7 @@ export declare class CPlusPlusRenderer extends ConvenienceRenderer {
154
164
  protected variantType(u: UnionType, inJsonNamespace: boolean): Sourcelike;
155
165
  protected ourQualifier(inJsonNamespace: boolean): Sourcelike;
156
166
  protected jsonQualifier(inJsonNamespace: boolean): Sourcelike;
157
- protected variantIndirection(needIndirection: boolean, typeSrc: Sourcelike): Sourcelike;
167
+ protected variantIndirection(type: Type, needIndirection: boolean, typeSrc: Sourcelike): Sourcelike;
158
168
  protected cppType(t: Type, ctx: TypeContext, withIssues: boolean, forceNarrowString: boolean, isOptional: boolean): Sourcelike;
159
169
  /**
160
170
  * similar to cppType, it practically gathers all the generated types within
@@ -216,19 +216,10 @@ const keywords = [
216
216
  "transaction_safe_dynamic",
217
217
  "NULL"
218
218
  ];
219
- /**
220
- * We can't use boost/std optional. They MUST have the declaration of
221
- * the given structure available, meaning we can't forward declare anything.
222
- * Which is bad as we have circles in Json schema, which require at least
223
- * forward declarability.
224
- * The next question, why isn't unique_ptr is enough here?
225
- * That problem relates to getter/setter. If using getter/setters we
226
- * can't/mustn't return a unique_ptr out of the class -> as that is the
227
- * sole reason why we have declared that as unique_ptr, so that only
228
- * the class owns it. We COULD return unique_ptr references, which practically
229
- * kills the uniqueness of the smart pointer -> hence we use shared_ptrs.
230
- */
231
- const optionalType = "std::shared_ptr";
219
+ /// Type to use as an optional if cycle breaking is required
220
+ const optionalAsSharedType = "std::shared_ptr";
221
+ /// Factory to use when creating an optional if cycle breaking is required
222
+ const optionalFactoryAsSharedType = "std::make_shared";
232
223
  /**
233
224
  * To be able to support circles in multiple files -
234
225
  * e.g. class#A using class#B using class#A (obviously not directly,
@@ -434,18 +425,124 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
434
425
  }
435
426
  if (_options.boost) {
436
427
  this._optionalType = "boost::optional";
428
+ this._optionalFactory = "boost::optional";
437
429
  this._nulloptType = "boost::none";
438
430
  this._variantType = "boost::variant";
439
431
  this._variantIndexMethodName = "which";
440
432
  }
441
433
  else {
442
434
  this._optionalType = "std::optional";
435
+ this._optionalFactory = "std::make_optional";
443
436
  this._nulloptType = "std::nullopt";
444
437
  this._variantType = "std::variant";
445
438
  this._variantIndexMethodName = "index";
446
439
  }
447
440
  this.setupGlobalNames();
448
441
  }
442
+ // union typeguard
443
+ isUnion(t) {
444
+ return t.kind === "union";
445
+ }
446
+ // Returns true if the type can be stored in
447
+ // a stack based optional type. This requires
448
+ // that the type does not require forward declaration.
449
+ isOptionalAsValuePossible(t) {
450
+ if (this.isForwardDeclaredType(t))
451
+ return false;
452
+ if (this.isUnion(t)) {
453
+ // There is something stinky about this test.
454
+ // There is special handling somewhere that if you
455
+ // have the following schema
456
+ // {
457
+ // "$schema": "http://json-schema.org/draft-06/schema#",
458
+ // "$ref": "#/definitions/List",
459
+ // "definitions": {
460
+ // "List": {
461
+ // "type": "object",
462
+ // "additionalProperties": false,
463
+ // "properties": {
464
+ // "data": {
465
+ // "type": "string"
466
+ // },
467
+ // "next": {
468
+ // "anyOf": [
469
+ // {
470
+ // "$ref": "#/definitions/List"
471
+ // }
472
+ // {
473
+ // "type": "null"
474
+ // }
475
+ // ]
476
+ // }
477
+ // },
478
+ // "required": [],
479
+ // "title": "List"
480
+ // }
481
+ // }
482
+ // }
483
+ // Then a variant is not output but the single item inlined
484
+ //
485
+ // struct TopLevel {
486
+ // std::optional<std::string> data;
487
+ // std::optional<TopLevel> next;
488
+ // };
489
+ //
490
+ // instead of
491
+ // struct TopLevel {
492
+ // std::optional<std::string> data;
493
+ // std::shared_ptr<TopLevel> next;
494
+ // };
495
+ //
496
+ // checking to see if the collapse of the variant has
497
+ // occured and then doing the isCycleBreakerType check
498
+ // on the single type the variant would contain seems
499
+ // to solve the problem. But does this point to a problem
500
+ // with the core library or with the CPlusPlus package
501
+ const [, nonNulls] = (0, TypeUtils_1.removeNullFromUnion)(t);
502
+ if (nonNulls.size === 1) {
503
+ const tt = (0, Support_1.defined)((0, collection_utils_1.iterableFirst)(nonNulls));
504
+ return !this.isCycleBreakerType(tt);
505
+ }
506
+ }
507
+ return !this.isCycleBreakerType(t);
508
+ }
509
+ isImplicitCycleBreaker(t) {
510
+ const kind = t.kind;
511
+ return kind === "array" || kind === "map";
512
+ }
513
+ // Is likely to return std::optional or boost::optional
514
+ optionalTypeStack() {
515
+ return this._optionalType;
516
+ }
517
+ // Is likely to return std::make_optional or boost::optional
518
+ optionalFactoryStack() {
519
+ return this._optionalFactory;
520
+ }
521
+ // Is likely to return std::shared_ptr
522
+ optionalTypeHeap() {
523
+ return optionalAsSharedType;
524
+ }
525
+ // Is likely to return std::make_shared
526
+ optionalFactoryHeap() {
527
+ return optionalFactoryAsSharedType;
528
+ }
529
+ // Returns the optional type most suitable for the given type.
530
+ // Classes that don't require forward declarations can be stored
531
+ // in std::optional ( or boost::optional )
532
+ optionalType(t) {
533
+ if (this.isOptionalAsValuePossible(t))
534
+ return this.optionalTypeStack();
535
+ else
536
+ return this.optionalTypeHeap();
537
+ }
538
+ // Returns a label that can be used to distinguish between
539
+ // heap and stack based optional handling methods
540
+ optionalTypeLabel(t) {
541
+ if (this.isOptionalAsValuePossible(t))
542
+ return "stack";
543
+ else
544
+ return "heap";
545
+ }
449
546
  getConstraintMembers() {
450
547
  return [
451
548
  {
@@ -672,7 +769,7 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
672
769
  if (!indirection) {
673
770
  return variant;
674
771
  }
675
- return [optionalType, "<", variant, ">"];
772
+ return [this.optionalType(u), "<", variant, ">"];
676
773
  }
677
774
  ourQualifier(inJsonNamespace) {
678
775
  return inJsonNamespace ? [(0, collection_utils_1.arrayIntercalate)("::", this._namespaceNames), "::"] : [];
@@ -680,10 +777,10 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
680
777
  jsonQualifier(inJsonNamespace) {
681
778
  return inJsonNamespace ? [] : "nlohmann::";
682
779
  }
683
- variantIndirection(needIndirection, typeSrc) {
780
+ variantIndirection(type, needIndirection, typeSrc) {
684
781
  if (!needIndirection)
685
782
  return typeSrc;
686
- return [optionalType, "<", typeSrc, ">"];
783
+ return [this.optionalType(type), "<", typeSrc, ">"];
687
784
  }
688
785
  cppType(t, ctx, withIssues, forceNarrowString, isOptional) {
689
786
  const inJsonNamespace = ctx.inJsonNamespace;
@@ -719,7 +816,7 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
719
816
  "std::vector<",
720
817
  this.cppType(arrayType.items, { needsForwardIndirection: false, needsOptionalIndirection: true, inJsonNamespace }, withIssues, forceNarrowString, false),
721
818
  ">"
722
- ], classType => this.variantIndirection(ctx.needsForwardIndirection && this.isForwardDeclaredType(classType) && !isOptional, [this.ourQualifier(inJsonNamespace), this.nameForNamedType(classType)]), mapType => {
819
+ ], classType => this.variantIndirection(classType, ctx.needsForwardIndirection && this.isForwardDeclaredType(classType) && !isOptional, [this.ourQualifier(inJsonNamespace), this.nameForNamedType(classType)]), mapType => {
723
820
  let keyType = this._stringType.getType();
724
821
  if (forceNarrowString) {
725
822
  keyType = "std::string";
@@ -733,14 +830,17 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
733
830
  ];
734
831
  }, enumType => [this.ourQualifier(inJsonNamespace), this.nameForNamedType(enumType)], unionType => {
735
832
  const nullable = (0, TypeUtils_1.nullableFromUnion)(unionType);
736
- if (nullable === null)
833
+ if (nullable !== null) {
834
+ isOptional = true;
835
+ return this.cppType(nullable, { needsForwardIndirection: false, needsOptionalIndirection: false, inJsonNamespace }, withIssues, forceNarrowString, false);
836
+ }
837
+ else {
737
838
  return [this.ourQualifier(inJsonNamespace), this.nameForNamedType(unionType)];
738
- isOptional = true;
739
- return this.cppType(nullable, { needsForwardIndirection: false, needsOptionalIndirection: false, inJsonNamespace }, withIssues, forceNarrowString, false);
839
+ }
740
840
  });
741
841
  if (!isOptional)
742
842
  return typeSource;
743
- return [optionalType, "<", typeSource, ">"];
843
+ return [this.optionalType(t), "<", typeSource, ">"];
744
844
  }
745
845
  /**
746
846
  * similar to cppType, it practically gathers all the generated types within
@@ -938,8 +1038,8 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
938
1038
  // Forward declarations for std::map<std::wstring, Key> (need to convert UTF16 <-> UTF8)
939
1039
  if (t instanceof Type_1.MapType && this._stringType !== this.NarrowString) {
940
1040
  const ourQualifier = this.ourQualifier(true);
941
- this.emitLine("template <>");
942
1041
  this.emitBlock(["struct adl_serializer<", ourQualifier, className, ">"], true, () => {
1042
+ this.emitLine("template <>");
943
1043
  this.emitLine("static void from_json(", this.withConst("json"), " & j, ", ourQualifier, className, " & x);");
944
1044
  this.emitLine("static void to_json(json & j, ", this.withConst([ourQualifier, className]), " & x);");
945
1045
  });
@@ -1045,9 +1145,9 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
1045
1145
  inJsonNamespace: false
1046
1146
  }, false, false);
1047
1147
  this.emitLine(assignment.wrap([], [
1048
- this._stringType.wrapEncodingChange([ourQualifier], [optionalType, "<", cppType, ">"], [optionalType, "<", toType, ">"], [
1148
+ this._stringType.wrapEncodingChange([ourQualifier], [this.optionalType(t), "<", cppType, ">"], [this.optionalType(t), "<", toType, ">"], [
1049
1149
  ourQualifier,
1050
- "get_optional<",
1150
+ `get_${this.optionalTypeLabel(t)}_optional<`,
1051
1151
  cppType,
1052
1152
  ">(j, ",
1053
1153
  this._stringType.wrapEncodingChange([ourQualifier], this._stringType.getType(), this.NarrowString.getType(), [this._stringType.createStringLiteral([(0, Strings_1.stringEscape)(json)])]),
@@ -1276,16 +1376,20 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
1276
1376
  this.emitLine("#ifndef NLOHMANN_OPT_HELPER");
1277
1377
  this.emitLine("#define NLOHMANN_OPT_HELPER");
1278
1378
  this.emitNamespaces(["nlohmann"], () => {
1279
- this.emitLine("template <typename T>");
1280
- this.emitBlock(["struct adl_serializer<", optionalType, "<T>>"], true, () => {
1281
- this.emitBlock(["static void to_json(json & j, ", this.withConst([optionalType, "<T>"]), " & opt)"], false, () => {
1282
- this.emitLine("if (!opt) j = nullptr; else j = *opt;");
1283
- });
1284
- this.ensureBlankLine();
1285
- this.emitBlock(["static ", optionalType, "<T> from_json(", this.withConst("json"), " & j)"], false, () => {
1286
- this.emitLine(`if (j.is_null()) return std::unique_ptr<T>(); else return std::unique_ptr<T>(new T(j.get<T>()));`);
1379
+ const emitAdlStruct = (optType, factory) => {
1380
+ this.emitLine("template <typename T>");
1381
+ this.emitBlock(["struct adl_serializer<", optType, "<T>>"], true, () => {
1382
+ this.emitBlock(["static void to_json(json & j, ", this.withConst([optType, "<T>"]), " & opt)"], false, () => {
1383
+ this.emitLine("if (!opt) j = nullptr; else j = *opt;");
1384
+ });
1385
+ this.ensureBlankLine();
1386
+ this.emitBlock(["static ", optType, "<T> from_json(", this.withConst("json"), " & j)"], false, () => {
1387
+ this.emitLine(`if (j.is_null()) return ${factory}<T>(); else return ${factory}<T>(j.get<T>());`);
1388
+ });
1287
1389
  });
1288
- });
1390
+ };
1391
+ emitAdlStruct(this.optionalTypeHeap(), this.optionalFactoryHeap());
1392
+ emitAdlStruct(this.optionalTypeStack(), this.optionalFactoryStack());
1289
1393
  });
1290
1394
  this.emitLine("#endif");
1291
1395
  }
@@ -1481,26 +1585,37 @@ class CPlusPlusRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
1481
1585
  this.ensureBlankLine();
1482
1586
  this.emitLine("#ifndef " + optionalMacroName);
1483
1587
  this.emitLine("#define " + optionalMacroName);
1484
- this.emitLine("template <typename T>");
1485
- this.emitBlock([
1486
- "inline ",
1487
- optionalType,
1488
- "<T> get_optional(",
1489
- this.withConst("json"),
1490
- " & j, ",
1491
- this.withConst("char"),
1492
- " * property)"
1493
- ], false, () => {
1494
- this.emitBlock(["if (j.find(property) != j.end())"], false, () => {
1495
- this.emitLine("return j.at(property).get<", optionalType, "<T>>();");
1588
+ const emitGetOptional = (optionalType, label) => {
1589
+ this.emitLine("template <typename T>");
1590
+ this.emitBlock([
1591
+ "inline ",
1592
+ optionalType,
1593
+ `<T> get_${label}_optional(`,
1594
+ this.withConst("json"),
1595
+ " & j, ",
1596
+ this.withConst("char"),
1597
+ " * property)"
1598
+ ], false, () => {
1599
+ this.emitLine(["auto it = j.find(property);"]);
1600
+ this.emitBlock(["if (it != j.end() && !it->is_null())"], false, () => {
1601
+ this.emitLine("return j.at(property).get<", optionalType, "<T>>();");
1602
+ });
1603
+ this.emitLine("return ", optionalType, "<T>();");
1496
1604
  });
1497
- this.emitLine("return ", optionalType, "<T>();");
1498
- });
1499
- this.ensureBlankLine();
1500
- this.emitLine("template <typename T>");
1501
- this.emitBlock(["inline ", optionalType, "<T> get_optional(", this.withConst("json"), " & j, std::string property)"], false, () => {
1502
- this.emitLine("return get_optional<T>(j, property.data());");
1503
- });
1605
+ this.ensureBlankLine();
1606
+ this.emitLine("template <typename T>");
1607
+ this.emitBlock([
1608
+ "inline ",
1609
+ optionalType,
1610
+ `<T> get_${label}_optional(`,
1611
+ this.withConst("json"),
1612
+ " & j, std::string property)"
1613
+ ], false, () => {
1614
+ this.emitLine(`return get_${label}_optional<T>(j, property.data());`);
1615
+ });
1616
+ };
1617
+ emitGetOptional(this.optionalTypeHeap(), "heap");
1618
+ emitGetOptional(this.optionalTypeStack(), "stack");
1504
1619
  this.emitLine("#endif");
1505
1620
  this.ensureBlankLine();
1506
1621
  }
@@ -54,10 +54,11 @@ export declare class DartRenderer extends ConvenienceRenderer {
54
54
  protected emitDescriptionBlock(lines: Sourcelike[]): void;
55
55
  protected emitBlock(line: Sourcelike, f: () => void): void;
56
56
  protected dartType(t: Type, withIssues?: boolean): Sourcelike;
57
- protected mapList(itemType: Sourcelike, list: Sourcelike, mapper: Sourcelike): Sourcelike;
58
- protected mapMap(valueType: Sourcelike, map: Sourcelike, valueMapper: Sourcelike): Sourcelike;
59
- protected fromDynamicExpression(t: Type, ...dynamic: Sourcelike[]): Sourcelike;
60
- protected toDynamicExpression(t: Type, ...dynamic: Sourcelike[]): Sourcelike;
57
+ protected mapList(isNullable: boolean, itemType: Sourcelike, list: Sourcelike, mapper: Sourcelike): Sourcelike;
58
+ protected mapMap(isNullable: boolean, valueType: Sourcelike, map: Sourcelike, valueMapper: Sourcelike): Sourcelike;
59
+ protected mapClass(isNullable: boolean, classType: ClassType, dynamic: Sourcelike): Sourcelike[];
60
+ protected fromDynamicExpression(isNullable: boolean | undefined, t: Type, ...dynamic: Sourcelike[]): Sourcelike;
61
+ protected toDynamicExpression(isNullable: boolean | undefined, t: Type, ...dynamic: Sourcelike[]): Sourcelike;
61
62
  protected emitClassDefinition(c: ClassType, className: Name): void;
62
63
  protected emitFreezedClassDefinition(c: ClassType, className: Name): void;
63
64
  protected emitEnumDefinition(e: EnumType, enumName: Name): void;
@@ -49,7 +49,6 @@ class DartTargetLanguage extends TargetLanguage_1.TargetLanguage {
49
49
  const mapping = new Map();
50
50
  mapping.set("date", "date");
51
51
  mapping.set("date-time", "date-time");
52
- // mapping.set("uuid", "uuid");
53
52
  return mapping;
54
53
  }
55
54
  makeRenderer(renderContext, untypedOptionValues) {
@@ -269,132 +268,97 @@ class DartRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
269
268
  this.emitLine("}");
270
269
  }
271
270
  dartType(t, withIssues = false) {
272
- return (0, TypeUtils_1.matchType)(t, _anyType => (0, Source_1.maybeAnnotated)(withIssues, Annotation_1.anyTypeIssueAnnotation, "dynamic"), _nullType => (0, Source_1.maybeAnnotated)(withIssues, Annotation_1.nullTypeIssueAnnotation, "dynamic"), _boolType => {
273
- if (this._options.nullSafety) {
274
- return ["bool", "?"];
275
- }
276
- return "bool";
277
- }, _integerType => {
278
- if (this._options.nullSafety) {
279
- return ["int", "?"];
280
- }
281
- return "int";
282
- }, _doubleType => {
283
- if (this._options.nullSafety) {
284
- return ["double", "?"];
285
- }
286
- return "double";
287
- }, _stringType => {
288
- if (this._options.nullSafety) {
289
- return ["String", "?"];
290
- }
291
- return "String";
292
- }, arrayType => {
293
- if (this._options.nullSafety) {
294
- return ["List<", this.dartType(arrayType.items, withIssues), ">", "?"];
295
- }
296
- return ["List<", this.dartType(arrayType.items, withIssues), ">"];
297
- }, classType => {
298
- if (this._options.nullSafety) {
299
- return [this.nameForNamedType(classType), "?"];
300
- }
301
- return this.nameForNamedType(classType);
302
- }, mapType => {
303
- if (this._options.nullSafety) {
304
- return [["Map<String, ", this.dartType(mapType.values, withIssues), ">"], "?"];
305
- }
306
- return ["Map<String, ", this.dartType(mapType.values, withIssues), ">"];
307
- }, enumType => {
308
- if (this._options.nullSafety) {
309
- return [this.nameForNamedType(enumType), "?"];
310
- }
311
- return this.nameForNamedType(enumType);
312
- }, unionType => {
271
+ const nullable = this._options.nullSafety && t.isNullable && !this._options.requiredProperties;
272
+ const withNullable = (s) => (nullable ? [s, "?"] : s);
273
+ return (0, TypeUtils_1.matchType)(t, _anyType => (0, Source_1.maybeAnnotated)(withIssues, Annotation_1.anyTypeIssueAnnotation, "dynamic"), _nullType => (0, Source_1.maybeAnnotated)(withIssues, Annotation_1.nullTypeIssueAnnotation, "dynamic"), _boolType => withNullable("bool"), _integerType => withNullable("int"), _doubleType => withNullable("double"), _stringType => withNullable("String"), arrayType => withNullable(["List<", this.dartType(arrayType.items, withIssues), ">"]), classType => withNullable(this.nameForNamedType(classType)), mapType => withNullable(["Map<String, ", this.dartType(mapType.values, withIssues), ">"]), enumType => withNullable(this.nameForNamedType(enumType)), unionType => {
313
274
  const maybeNullable = (0, TypeUtils_1.nullableFromUnion)(unionType);
314
275
  if (maybeNullable === null) {
315
276
  return "dynamic";
316
277
  }
317
- return this.dartType(maybeNullable, withIssues);
278
+ return withNullable(this.dartType(maybeNullable, withIssues));
318
279
  }, transformedStringType => {
319
280
  switch (transformedStringType.kind) {
320
281
  case "date-time":
321
282
  case "date":
322
- return this._options.nullSafety ? ["DateTime", "?"] : "DateTime";
283
+ return withNullable("DateTime");
323
284
  default:
324
- return this._options.nullSafety ? ["String", "?"] : "String";
285
+ return withNullable("String");
325
286
  }
326
287
  });
327
288
  }
328
- mapList(itemType, list, mapper) {
329
- if (this._options.nullSafety) {
289
+ mapList(isNullable, itemType, list, mapper) {
290
+ if (this._options.nullSafety && isNullable && !this._options.requiredProperties) {
330
291
  return [list, " == null ? [] : ", "List<", itemType, ">.from(", list, "!.map((x) => ", mapper, "))"];
331
292
  }
332
293
  return ["List<", itemType, ">.from(", list, ".map((x) => ", mapper, "))"];
333
294
  }
334
- mapMap(valueType, map, valueMapper) {
335
- if (this._options.nullSafety) {
295
+ mapMap(isNullable, valueType, map, valueMapper) {
296
+ if (this._options.nullSafety && isNullable && !this._options.requiredProperties) {
336
297
  return ["Map.from(", map, "!).map((k, v) => MapEntry<String, ", valueType, ">(k, ", valueMapper, "))"];
337
298
  }
338
299
  return ["Map.from(", map, ").map((k, v) => MapEntry<String, ", valueType, ">(k, ", valueMapper, "))"];
339
300
  }
340
- fromDynamicExpression(t, ...dynamic) {
301
+ mapClass(isNullable, classType, dynamic) {
302
+ if (this._options.nullSafety && isNullable && !this._options.requiredProperties) {
303
+ return [dynamic, " == null ? null : ", this.nameForNamedType(classType), ".", this.fromJson, "(", dynamic, ")"];
304
+ }
305
+ return [this.nameForNamedType(classType), ".", this.fromJson, "(", dynamic, ")"];
306
+ }
307
+ //If the first time is the unionType type, after nullableFromUnion conversion,
308
+ //the isNullable property will become false, which is obviously wrong,
309
+ //so add isNullable property
310
+ fromDynamicExpression(isNullable = false, t, ...dynamic) {
341
311
  return (0, TypeUtils_1.matchType)(t, _anyType => dynamic, _nullType => dynamic, // FIXME: check null
342
312
  // FIXME: check null
343
- _boolType => dynamic, _integerType => dynamic, _doubleType => [dynamic, ".toDouble()"], _stringType => dynamic, arrayType => this.mapList(this.dartType(arrayType.items), dynamic, this.fromDynamicExpression(arrayType.items, "x")), classType => [this.nameForNamedType(classType), ".", this.fromJson, "(", dynamic, ")"], mapType => this.mapMap(this.dartType(mapType.values), dynamic, this.fromDynamicExpression(mapType.values, "v")), enumType => {
344
- if (this._options.nullSafety) {
345
- return [(0, Support_1.defined)(this._enumValues.get(enumType)), "!.map[", dynamic, "]"];
346
- }
347
- return [(0, Support_1.defined)(this._enumValues.get(enumType)), ".map[", dynamic, "]"];
313
+ _boolType => dynamic, _integerType => dynamic, _doubleType => [dynamic, this._options.nullSafety ? "?.toDouble()" : ".toDouble()"], _stringType => dynamic, arrayType => this.mapList(isNullable || arrayType.isNullable, this.dartType(arrayType.items), dynamic, this.fromDynamicExpression(arrayType.items.isNullable, arrayType.items, "x")), classType => this.mapClass(isNullable || classType.isNullable, classType, dynamic), mapType => this.mapMap(mapType.isNullable || isNullable, this.dartType(mapType.values), dynamic, this.fromDynamicExpression(mapType.values.isNullable, mapType.values, "v")), enumType => {
314
+ return [(0, Support_1.defined)(this._enumValues.get(enumType)), ".map[", dynamic, this._options.nullSafety ? "]!" : "]"];
348
315
  }, unionType => {
349
316
  const maybeNullable = (0, TypeUtils_1.nullableFromUnion)(unionType);
350
317
  if (maybeNullable === null) {
351
318
  return dynamic;
352
319
  }
353
- if (maybeNullable.kind === "array") {
354
- return [dynamic, " == null ? [] : ", this.fromDynamicExpression(maybeNullable, dynamic)];
355
- }
356
- return dynamic;
320
+ return this.fromDynamicExpression(unionType.isNullable, maybeNullable, dynamic);
357
321
  }, transformedStringType => {
358
322
  switch (transformedStringType.kind) {
359
323
  case "date-time":
360
324
  case "date":
325
+ if ((transformedStringType.isNullable || isNullable) && !this._options.requiredProperties && this._options.nullSafety) {
326
+ return [dynamic, " == null ? null : ", "DateTime.parse(", dynamic, ")"];
327
+ }
361
328
  return ["DateTime.parse(", dynamic, ")"];
362
329
  default:
363
330
  return dynamic;
364
331
  }
365
332
  });
366
333
  }
367
- toDynamicExpression(t, ...dynamic) {
368
- return (0, TypeUtils_1.matchType)(t, _anyType => dynamic, _nullType => dynamic, _boolType => dynamic, _integerType => dynamic, _doubleType => dynamic, _stringType => dynamic, arrayType => this.mapList("dynamic", dynamic, this.toDynamicExpression(arrayType.items, "x")), _classType => {
369
- if (this._options.nullSafety) {
370
- return [dynamic, "!.", this.toJson, "()"];
334
+ //If the first time is the unionType type, after nullableFromUnion conversion,
335
+ //the isNullable property will become false, which is obviously wrong,
336
+ //so add isNullable property
337
+ toDynamicExpression(isNullable = false, t, ...dynamic) {
338
+ return (0, TypeUtils_1.matchType)(t, _anyType => dynamic, _nullType => dynamic, _boolType => dynamic, _integerType => dynamic, _doubleType => dynamic, _stringType => dynamic, arrayType => this.mapList(arrayType.isNullable || isNullable, "dynamic", dynamic, this.toDynamicExpression(arrayType.items.isNullable, arrayType.items, "x")), _classType => {
339
+ if (this._options.nullSafety && (_classType.isNullable || isNullable) && !this._options.requiredProperties) {
340
+ return [dynamic, "?.", this.toJson, "()"];
371
341
  }
372
342
  return [dynamic, ".", this.toJson, "()"];
373
- }, mapType => this.mapMap("dynamic", dynamic, this.toDynamicExpression(mapType.values, "v")), enumType => {
374
- if (this._options.nullSafety) {
375
- return [(0, Support_1.defined)(this._enumValues.get(enumType)), ".reverse![", dynamic, "]"];
376
- }
343
+ }, mapType => this.mapMap(mapType.isNullable || isNullable, "dynamic", dynamic, this.toDynamicExpression(mapType.values.isNullable, mapType.values, "v")), enumType => {
377
344
  return [(0, Support_1.defined)(this._enumValues.get(enumType)), ".reverse[", dynamic, "]"];
378
345
  }, unionType => {
379
346
  const maybeNullable = (0, TypeUtils_1.nullableFromUnion)(unionType);
380
347
  if (maybeNullable === null) {
381
348
  return dynamic;
382
349
  }
383
- if (maybeNullable.kind === "array") {
384
- return [dynamic, " == null ? [] : ", this.toDynamicExpression(maybeNullable, dynamic)];
385
- }
386
- return dynamic;
350
+ return this.toDynamicExpression(unionType.isNullable, maybeNullable, dynamic);
387
351
  }, transformedStringType => {
388
352
  switch (transformedStringType.kind) {
389
353
  case "date-time":
390
- if (this._options.nullSafety) {
354
+ if (this._options.nullSafety && !this._options.requiredProperties && (transformedStringType.isNullable || isNullable)) {
391
355
  return [dynamic, "?.toIso8601String()"];
392
356
  }
393
357
  return [dynamic, ".toIso8601String()"];
394
358
  case "date":
395
- if (this._options.nullSafety) {
359
+ if (this._options.nullSafety && !this._options.requiredProperties && (transformedStringType.isNullable || isNullable)) {
396
360
  return [
397
- '"${',
361
+ "\"${",
398
362
  dynamic,
399
363
  "!.year.toString().padLeft(4, '0')",
400
364
  "}-${",
@@ -405,7 +369,7 @@ class DartRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
405
369
  ];
406
370
  }
407
371
  return [
408
- '"${',
372
+ "\"${",
409
373
  dynamic,
410
374
  ".year.toString().padLeft(4, '0')",
411
375
  "}-${",
@@ -433,8 +397,9 @@ class DartRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
433
397
  else {
434
398
  this.emitLine(className, "({");
435
399
  this.indent(() => {
436
- this.forEachClassProperty(c, "none", (name, _, _p) => {
437
- this.emitLine(this._options.requiredProperties ? "required " : "", "this.", name, ",");
400
+ this.forEachClassProperty(c, "none", (name, _, prop) => {
401
+ const required = this._options.requiredProperties || (this._options.nullSafety && !prop.type.isNullable);
402
+ this.emitLine(required ? "required " : "", "this.", name, ",");
438
403
  });
439
404
  });
440
405
  this.emitLine("});");
@@ -482,7 +447,7 @@ class DartRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
482
447
  this.emitLine("factory ", className, ".", this.fromJson, "(Map<String, dynamic> json) => ", className, "(");
483
448
  this.indent(() => {
484
449
  this.forEachClassProperty(c, "none", (name, jsonName, property) => {
485
- this.emitLine(name, ": ", this.fromDynamicExpression(property.type, 'json["', stringEscape(jsonName), '"]'), ",");
450
+ this.emitLine(name, ": ", this.fromDynamicExpression(property.type.isNullable, property.type, "json[\"", stringEscape(jsonName), "\"]"), ",");
486
451
  });
487
452
  });
488
453
  this.emitLine(");");
@@ -490,7 +455,7 @@ class DartRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
490
455
  this.emitLine("Map<String, dynamic> ", this.toJson, "() => {");
491
456
  this.indent(() => {
492
457
  this.forEachClassProperty(c, "none", (name, jsonName, property) => {
493
- this.emitLine('"', stringEscape(jsonName), '": ', this.toDynamicExpression(property.type, name), ",");
458
+ this.emitLine("\"", stringEscape(jsonName), "\": ", this.toDynamicExpression(property.type.isNullable, property.type, name), ",");
494
459
  });
495
460
  });
496
461
  this.emitLine("};");
@@ -531,7 +496,7 @@ class DartRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
531
496
  this.indent(() => {
532
497
  this.forEachEnumCase(e, "none", (name, jsonName, pos) => {
533
498
  const comma = pos === "first" || pos === "middle" ? "," : [];
534
- this.emitLine('"', stringEscape(jsonName), '": ', enumName, ".", name, comma);
499
+ this.emitLine("\"", stringEscape(jsonName), "\": ", enumName, ".", name, comma);
535
500
  });
536
501
  });
537
502
  this.emitLine("});");
@@ -541,12 +506,12 @@ class DartRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
541
506
  this.ensureBlankLine();
542
507
  this.emitMultiline(`class EnumValues<T> {
543
508
  Map<String, T> map;
544
- Map<T, String>? reverseMap;
509
+ late Map<T, String> reverseMap;
545
510
 
546
511
  EnumValues(this.map);
547
512
 
548
- Map<T, String>? get reverse {
549
- reverseMap ??= map.map((k, v) => MapEntry(v, k));
513
+ Map<T, String> get reverse {
514
+ reverseMap = map.map((k, v) => MapEntry(v, k));
550
515
  return reverseMap;
551
516
  }
552
517
  }`);
@@ -556,9 +521,9 @@ class DartRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
556
521
  if (!this._options.justTypes && !this._options.codersInClass) {
557
522
  this.forEachTopLevel("leading-and-interposing", (t, name) => {
558
523
  const { encoder, decoder } = (0, Support_1.defined)(this._topLevelDependents.get(name));
559
- this.emitLine(this.dartType(t), " ", decoder, "(String str) => ", this.fromDynamicExpression(t, "json.decode(str)"), ";");
524
+ this.emitLine(this.dartType(t), " ", decoder, "(String str) => ", this.fromDynamicExpression(t.isNullable, t, "json.decode(str)"), ";");
560
525
  this.ensureBlankLine();
561
- this.emitLine("String ", encoder, "(", this.dartType(t), " data) => json.encode(", this.toDynamicExpression(t, "data"), ");");
526
+ this.emitLine("String ", encoder, "(", this.dartType(t), " data) => json.encode(", this.toDynamicExpression(t.isNullable, t, "data"), ");");
562
527
  // this.emitBlock(["String ", encoder, "(", this.dartType(t), " data)"], () => {
563
528
  // this.emitJsonEncoderBlock(t);
564
529
  // });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quicktype-core",
3
- "version": "20.0.26",
3
+ "version": "21.0.0",
4
4
  "description": "The quicktype engine as a library",
5
5
  "license": "Apache-2.0",
6
6
  "main": "dist/index.js",