Kucera.Jan.CZ
Kucera.Jan.CZ

Reputation: 776

JACKSON: Object Identifier for external

I am working with Jackson parsing and wondering if there is any way in Jackson to create such JSON document?

"fields": {
    "A" : { "ref" : 1},
    "B" : { "ref" : 2},
    "C" : { "ref" : 1}
},
"refs" : [
    {"@id" : 1, "values" : ["X", "Y", "Z"] },
    {"@id" : 2, "values" : ["1", "2", "3] }
]

Where "A" will have the reference to array of strings defined in "refs" element

Upvotes: 0

Views: 137

Answers (1)

Sharon Ben Asher
Sharon Ben Asher

Reputation: 14328

It can be done with the help of Jackson's Object Identity feature:

the values collections need to be wrapped in their own class that is annotated so that Jackson generates object id for distinct collections:

@JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="@id")
public class Values
{
    public List<String> values = new ArrayList<>();

    public Values() {}

    public Values(String... values) {
        this.values = Arrays.asList(values);
    }

    /**
     * implement equals() and hashCode() so that instances can be put into Maps Sets and such  
     */
    @Override
    public boolean equals(Object other) {
        return other instanceof Values ? ((Values)other).values.equals(values) : false ; 
    }

    @Override
    public int hashCode() {
        return values.hashCode(); 
    }
}

the following class wraps ref and fields. serialization order is exlicitly defined so that jackson will generate object ids for the contents of refs

@JsonPropertyOrder({"refs", "fields"})
public class MyClass
{
    public Set<Values> refs = new HashSet<>();
    public Map<String, Values> fields = new HashMap<>(); 

    public MyClass()
    {
        Values v1 = new Values("X", "Y", "Z");
        Values v2 = new Values("1", "2", "3");
        fields.put("A", v1);
        fields.put("B", v2);
        fields.put("C", v1);
        fields.values().forEach(value -> refs.add(value));
    }
}

serialization of MyClass

new ObjectMapper().writeValue(System.out, new MyClass());

produces

{"refs":[{"@id":1,"values":["1","2","3"]},{"@id":2,"values":["X","Y","Z"]}],"fields":{"A":2,"B":1,"C":2}}

Upvotes: 1

Related Questions