Fix #512: Add @JsonWrapped annotation for grouping scalar fields into nested JSON objects#5715
Conversation
…o nested JSON objects Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Submitting this for review. |
1 similar comment
| @@ -0,0 +1,75 @@ | |||
| package tools.jackson.databind.annotation; | |||
There was a problem hiding this comment.
Since there's nothing databind-specific, this belongs in jackson-annotations, but for now can keep it here while considering rest of implementation.
(only annotations that depend on something in databind should be added within it)
There was a problem hiding this comment.
@sri-adarsh-kumar Could you do a PR against https://github.com/FasterXML/jackson-annotations/ for this addition?
There was a problem hiding this comment.
Created FasterXML/jackson-annotations#346
I think the build is failing for this PR as the SNAPSHOT version of jackson-annotations dependency does not yet contain the new annotation.
| * <li>The wrapper name ({@code value()}) must be non-empty.</li> | ||
| * <li>The wrapper name must not conflict with an existing non-wrapped property on the same bean.</li> | ||
| * <li>Not supported on {@code @JsonCreator} constructor or factory-method parameters.</li> | ||
| * <li>MVP limitation: {@code @JsonView} on inner wrapped fields is ignored — the wrapper |
There was a problem hiding this comment.
Views are tricky here, understood.
| Set<SettableBeanProperty> wrappedPropSet = new HashSet<>(); | ||
| for (SettableBeanProperty prop : allProps) { | ||
| AnnotatedMember member = prop.getMember(); | ||
| if (member == null) continue; |
There was a problem hiding this comment.
style: always use curly braces:
if (member == null) {
continue;
}
There was a problem hiding this comment.
Changed.
Are there any format check plugins or equivalent for this repo?
|
|
||
| @Override | ||
| public String findWrappedGroupName(MapperConfig<?> config, AnnotatedMember member) { | ||
| String r = _primary.findWrappedGroupName(config, member); |
There was a problem hiding this comment.
This will not work properly with case of enabled = false, I think.
| * | ||
| * @since 3.1 | ||
| */ | ||
| public static boolean isScalarType(JavaType type) { |
There was a problem hiding this comment.
I am not sure why we'd want to limit handling to scalar types, so probably need not comment on implementation.
1 similar comment
…ntract and validation Cleaned up the @JsonWrapped annotation implementation to use a three-value return contract for the wrapper name: null (not present), empty string (explicitly disabled in mix-ins), or non-empty string (active wrapper). Removed the redundant 'enabled' flag and simplified validation logic in BeanDeserializerBase. Updated WrappedPropertyHandler method signatures. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
…ections, maps, arrays Removes the scalar-only validation guards from BeanSerializerFactory and BeanDeserializerBase that blocked non-scalar types. The wrapper contract is unchanged — inner fields delegate to their own serializers/deserializers, so any Jackson-serializable type works without new machinery. Updates Javadoc, README, and converts former rejection tests to positive tests; adds serialization, deserialization, and round-trip coverage for POJO, List, Map, Array, mixed-type, and nested-wrapping scenarios. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
fe5783b to
40393a0
Compare
1 similar comment
|
@cowtowncoder Small Reminder. |
- Delete tools.jackson.databind.annotation.JsonWrapped (moved to
com.fasterxml.jackson.annotation.JsonWrapped in jackson-annotations)
- Update JacksonAnnotationIntrospector import to new package
- Update imports in JsonWrapped{Serialization,Deserialization,Validation}Test
- Fix README Javadoc link to point to jackson-annotations repo
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…adarsh-kumar/jackson-databind into feature/512-json-wrapped-annotation
Add `!ann.enabled()` check in `JacksonAnnotationIntrospector.findWrappedGroupName`, mirroring the identical pattern in `findUnwrappingNameTransformer` for `@JsonUnwrapped`. When `enabled=false`, the method now returns `null` so chained introspectors are unaffected — the empty-string sentinel remains the hard-disable mechanism. Also updates the `AnnotationIntrospector.findWrappedGroupName` Javadoc to document the `enabled=false` → null mapping, and adds three TDD tests covering the new behaviour via mix-in (serialization + deserialization) and direct annotation. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Due to timing, unfortunately I think this needs to go in 3.3, not 3.2 -- I am trying to close up 3.2 and this results in significant internal changes. Thank you for all your work here @sri-adarsh-kumar . |
Summary
Closes #512. Introduces
@JsonWrapped, a field-level annotation that groups multiple scalar properties under a single named wrapper object in the serialized JSON and reads them back during deserialization.PR to introduce annotation in FasterXML/jackson-annotations#346
Usage:
What's in the MVP
Serialization (grouping scalar fields into a named nested object) and deserialization (reading from the wrapper object back into flat fields), with full support for
@JsonPropertyon inner fields, multiple wrapper groups, non-contiguous fields,@JsonPropertyOrder,enabled=false, and round-trip correctness. Validation rejects non-scalar types, empty wrapper names, name conflicts, and combined use with@JsonUnwrapped.What's NOT in the MVP
@JsonViewon inner wrapped fields is ignored — the wrapper always emits all its fields regardless of active view. Class-level@JsonFilterapplies to the wrapper property itself (by wrapper name) but not to individual inner fields, and class-level@JsonInclude(e.g.NON_NULL) still applies to inner fields during serialization.Please add the
gen-ailabel to this PR.