json_annotation_lenient 1.2.0
json_annotation_lenient: ^1.2.0 copied to clipboard
Lenient JSON conversion for json_serializable — coerce loose int/double/num/bool/String/DateTime values instead of throwing, plus a drop-in build_runner builder that auto-fills type-based defaults for [...]
Changelog #
1.2.0 #
Added #
- New
options.page_width/options.trailing_commasforjson_annotation_lenient:auto_default—dart_style's publicDartFormatterAPI never reads a project'sanalysis_options.yamlformatter:section at all (that logic is private todart_style's own CLI), so generated.g.dartpreviously always useddart_style's built-in defaults regardless of your project's configured page width or trailing-comma style. Set these explicitly to match. - The builder now also auto-detects
formatter: page_width:/trailing_commas:from the nearestanalysis_options.yaml(walking up from the project root) whenoptions.page_width/options.trailing_commasaren't set explicitly — a from-scratch, simplified reimplementation that follows a single local (non-package:)include:path per file. Ananalysis_options.yamlwhoseformatter:section lives behind apackage:include isn't picked up; use the explicit options in that case. An explicitoptions:value always wins over auto-detection.
1.1.0 #
Changed #
- Behavior change:
autoDefaultJsonBuildernow defaultsexplicit_to_jsontotruewhen a consuming project'sbuild.yamldoesn't set it at all (nested@JsonSerializablefields need it to serialize correctly almost all the time, and the stockjson_serializabledefault offalsemeant every consumer had to opt in by hand). If your project relies on the old implicit-toJsonbehavior for nested objects, addexplicit_to_json: falseexplicitly under this builder'soptions:— an explicit value in either direction is always honored; this only fills the gap when the key is absent.
1.0.0 #
Fixed #
LenientBoolConverternow accepts numericdoublevalues and normalizes string input case-insensitively ("TRUE","Yes", ...); an unrecognized string now throws instead of silently returningfalse, matching every other converter.LenientIntConverternow accepts decimal strings ("42.5") via adoublefallback, and throws instead of producing a bogusintfor non-finite (NaN/Infinity) input.LenientDateTimeConverterno longer misreads an 8-digityyyyMMddstring (e.g."20240101") as an epoch-seconds timestamp; out-of-range epoch values now throw instead of raising an unrelatedRangeError.- All converters raise English
FormatExceptions naming the offending value's runtime type, instead of a Chinese-only message with no type info. - The
options.lenientyml no longer accepts adoubleliteral for anintdefault (it produced code that failed to compile);doubledefaults are now always rendered with an explicit.0. - The builder now warns at build time when
@LenientConverter/options.lenientis active on a library that doesn't importpackage:json_annotation_lenient/json_annotation_lenient.dart(a yml-only setup needs that import; without it the generated code fails with an undefined-name error) and skips the converter rewrite for that library rather than emitting code that won't compile. @DisableLenient()/ a field-level@LenientConverter(...)on an inherited field is now honored — previously only the class's own fields were scanned.- The
json['x'] == null ? d : const Converter().fromJson(json['x'])fold now only applies to our ownLenient*Converterclasses, so it no longer rewrites a third-partyJsonConverterinto a call shape it may not support. Set<T>fields are now covered by the same auto-default rewrite asList<T>(.toSet()alongside.toList()).
Performance #
- The generated-source rewrite now applies all edits in a single
StringBufferpass instead of repeatedString.replaceRangecalls (previously O(edits × file size) per build).
Docs #
- Removed a
builders:block from both READMEs'build.yamlexample — it registered a second builder that collided with this package's own (auto_apply: none) declaration and would failbuild_runnerwith a "conflicting outputs" error. - Fixed stale
lib/tool/build/.../lib/utils/...path references in dartdoc comments (pre-restructuring paths that don't exist in this package). environment.sdklowered floor corrected to^3.11.0to match whatanalyzer/build/dart_styleactually require — the previous^3.5.0advertised a compatibility this package couldn't deliver.
0.2.0 #
Builder #
-
New
options.lenientsection inbuild.yaml: turn leniency on/off per scalar type (int/double/num/bool/string/dateTime) project-wide, and override each type's fallback default value — no annotation needed on the model classes at all.options: lenient: int: enabled: true defaultValue: 0 string: enabled: true defaultValue: "" dateTime: enabled: false utc: falseEvery key is optional; only what you write is applied. Precedence, highest first: a field's own
@LenientConverter(...)→ the ymlenabled:→ the class-level@LenientConverter(...).@DisableLenient()still opts a field out of everything. For default values: a field's@JsonKey(defaultValue:)→ the ymldefaultValue:→ the built-in type default. -
dateTimeacceptsenabled:/utc:but notdefaultValue:(DateTimehas no const constructor); adefaultValue:written there is ignored rather than an error. Malformed entries anywhere in thelenient:section are skipped instead of failing the build. -
A yml
defaultValue:also replaces the plain auto-default injected into non-lenient fields (json['x'] as String? ?? '<yours>'). -
A class with no
@LenientConverter/@DisableLenientannotation at all is now still processed, so a yml-only setup works.
0.1.0 #
Initial release.
Extracted from an app's internal json_serializable tooling into a
standalone package.
Converters #
LenientIntConverter/LenientDoubleConverter/LenientNumConverter/LenientBoolConverter/LenientStringConverter— accept a small set of common alternate JSON shapes (numeric strings,"true"/"1", mismatched numeric subtypes, ...) instead of throwing, with a per-field fallback default.LenientDateTimeConverter— accepts ISO 8601 strings, a few non-standard string formats (/date separator, space instead ofT), and epoch numbers whose unit (seconds/milliseconds/microseconds) is guessed from magnitude;dateTimeUtccontrols how timezone-less values are interpreted.@LenientConverter(...)class-level annotation to turn on leniency for every field of a given scalar type at once;@DisableLenient()to opt a single field out entirely.
Builder #
autoDefaultJsonBuilder(package:json_annotation_lenient/builder.dart) — a build_runner builder that replaces the stockjson_serializablebuilder. Auto-fills type-based defaults ('',0,0.0,false,const [],const {}) for non-nullable fields with no explicit@JsonKey(defaultValue:), and rewrites matching fields to route through theLenient*Converterclasses when a class/field opts in via@LenientConverter.