diff --git a/src/main/java/com/ankurm/jackson3/part3annotations/D04CreatorsAndUnwrapping.java b/src/main/java/com/ankurm/jackson3/part3annotations/D04CreatorsAndUnwrapping.java new file mode 100644 index 0000000..8144d95 --- /dev/null +++ b/src/main/java/com/ankurm/jackson3/part3annotations/D04CreatorsAndUnwrapping.java @@ -0,0 +1,71 @@ +package com.ankurm.jackson3.part3annotations; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonUnwrapped; +import tools.jackson.databind.json.JsonMapper; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Post: Jackson Annotations Cheat Sheet — https://ankurm.com/jackson-annotations-guide/ + * Sections: "@JsonCreator", plus @JsonUnwrapped which the post's table lists but + * never demonstrates. @JsonAnyGetter/@JsonAnySetter are beyond the post entirely. + */ +public class D04CreatorsAndUnwrapping { + + /** Immutable class with no setters: the creator tells Jackson how to build it. */ + public static class ImmutablePoint { + private final double xCoordinate; + private final double yCoordinate; + + @JsonCreator + public ImmutablePoint(@JsonProperty("x") double xCoordinate, + @JsonProperty("y") double yCoordinate) { + this.xCoordinate = xCoordinate; + this.yCoordinate = yCoordinate; + } + @JsonProperty("x") public double getXCoordinate() { return xCoordinate; } + @JsonProperty("y") public double getYCoordinate() { return yCoordinate; } + @Override public String toString() { + return "ImmutablePoint(x=" + xCoordinate + ", y=" + yCoordinate + ")"; + } + } + + public record Address(String street, String city) { } + + /** @JsonUnwrapped flattens the nested object into the parent's JSON object. */ + public static class Customer { + public String customerName; + @JsonUnwrapped public Address address; + public Customer() { } + public Customer(String n, Address a) { customerName = n; address = a; } + } + + /** Any unmapped properties land in a Map instead of being dropped. */ + public static class FlexiblePayload { + public String knownField; + private final Map extras = new LinkedHashMap<>(); + @JsonAnyGetter public Map extras() { return extras; } + @JsonAnySetter public void put(String k, Object v) { extras.put(k, v); } + } + + public static void main(String[] args) { + JsonMapper mapper = JsonMapper.builder().build(); + + ImmutablePoint point = mapper.readValue("{\"x\":3.5,\"y\":7.2}", ImmutablePoint.class); + System.out.println("creator : " + point); + System.out.println("round-trip: " + mapper.writeValueAsString(point)); + + System.out.println("unwrapped : " + mapper.writeValueAsString( + new Customer("Alice", new Address("123 Main St", "Springfield")))); + + FlexiblePayload flexible = mapper.readValue( + "{\"knownField\":\"a\",\"surprise\":1,\"another\":[true,false]}", FlexiblePayload.class); + System.out.println("any-setter: " + flexible.extras()); + System.out.println("any-getter: " + mapper.writeValueAsString(flexible)); + } +}