json-io 4.101.0
Maven Central: com.cedarsoftware:json-io:4.101.0 (requires java-util 4.101.0+)
Highlights
New APIs
WriteOptionsBuilder.standardJson()— one-call convenience settingshowTypeInfoNever(),showRootTypeInfo(false),cycleSupport(false),stringifyMapKeys(true),useMetaPrefixDollar(), and ISO-8601 date formatting. Produces Jackson-compatible JSON for normal POJO/List/Map cases. Chainable. Will become the default in 5.0.0.WriteOptionsBuilder.namingStrategy(IoNaming.Strategy)— global naming strategy applied to all classes without a per-class@IoNaming/@JsonNaming. Priority: per-field@IoProperty/@JsonProperty> per-class annotation > global strategy > field name as-is. Two new enum values:UPPER_SNAKE_CASEandLOWER_CASE(full set:SNAKE_CASE,UPPER_SNAKE_CASE,KEBAB_CASE,UPPER_CAMEL_CASE,LOWER_DOT_CASE,LOWER_CASE).WriteOptionsBuilder.stringifyMapKeys(boolean)— non-String map keys with bidirectional String conversion (Long,UUID,Enum,Date, etc.) written as plain JSON object keys instead of@keys/@itemsparallel-array form. Defaultfalsefor JSON (backward-compat),truefor JSON5.WriteOptionsBuilder.preserveLeafContainerIdentity(boolean)— whenfalse(the new default),traceReferencesskips containers holding only non-referenceable leaves (List<String>,Map<UUID, Date>,String[], etc.), matching Jackson's default identity semantics.WriteOptionsBuilder.writeOptionalAsObject(boolean)— set totruefor legacy{"present":true,"value":X}form; defaultfalsewrites Optionals as bare primitive values.- 1-arg convenience overloads:
JsonIo.toJson(obj),toToon(obj),toJava(json),toJava(stream),fromToon(toon),fromToon(stream).
Performance
- Full-suite performance pass — all 8 Read/Write ratios under 2.0x vs Jackson on a warm JVM (best 1.32x JsonIo Read toMaps, worst ~1.97x Toon Read toJava).
- Switched all hot-path
ClassValueMap/ClassValueSetlookups to the newgetByClass(Class)/containsClass(Class)fast-path APIs (added in java-util 4.101.0). AnnotationResolver.getMetadata— split into trivially-inlineable fast path +scanAndCachecold path. Fast-path self-time dropped ~50%.ObjectResolver.traverseFields— hoisted per-objectAnnotationResolver.getMetadatacall out of the per-field loop (~20% of Resolver-phase samples).ReadOptions.isNonReferenceableClass/isNotCustomReaderClass— memoized via per-instanceClassValue<Boolean>caches (mirrorsWriteOptions.nonRefCache).JsonWriter.traceReferences— filters non-referenceable leaves at push site (save deque push+pop per leaf). JsonIo Write cycle=true toJava −5.8%, toMaps −7.5%.ToonWriter— precomputed key-quoting decision atWriteFieldPlanbuild time (eliminates per-fieldConcurrentHashMap.get— 11.7% of ToonWriter samples). Toon Write cycle=false toJava −5.0%.JsonWriter.writeField/ToonWriter.writeFieldEntry— primitive+String fast paths bypass full dispatch for the most common field-value types.ToonWriter.writeMap— skipshasComplexKeysiteration when the enclosing field's declared Map key type is Converter-stringifiable.JsonWriter.writeCollectionElement— POJO short-circuit forcycleSupport=falsecollapses 4-level dispatch to 2 levels.
Bug fixes
Optional,OptionalInt,OptionalLong,OptionalDouble— all four now write Jackson/Gson-compatible primitive form by default (Optional.empty()→null,Optional.of(X)→X). Prior behavior emitted invalid JSON forOptional({null}or{"hello"}) and broken POJO form for the three primitive Optionals. Field-type-aware coercion wraps bare scalars into the appropriate Optional variant on read. Reader accepts both new and legacy object form for backward compatibility. Reported by Jim Ronan (*/dxg Health).JsonWriter.writeLongDirect()— inner digit-extraction loop usedint qwhich silently truncatedLong.MIN_VALUE(rendered as-206158430208instead of-9223372036854775808). Fixed by usinglong q.
Jackson-alignment (opt-in)
WriteOptionsBuilder.standardJson()andjson5()now also configure ISO-8601 date formatting forjava.util.Date/java.sql.Date. Matches Spring Boot's default Jackson configuration (WRITE_DATES_AS_TIMESTAMPS=false).
Full changelog: https://github.com/jdereg/json-io/blob/master/changelog.md