package com.fasterxml.jackson.databind.objectid; import java.net.URI; import java.util.*; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.*; public class TestObjectIdWithEquals extends BaseMapTest { @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id", scope=Foo.class) static class Foo { public int id; public List<Bar> bars = new ArrayList<Bar>(); public List<Bar> otherBars = new ArrayList<Bar>(); public Foo() { } public Foo(int i) { id = i; } } @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id", scope=Bar.class) static class Bar { public int id; public Bar() { } public Bar(int i) { id = i; } @Override public int hashCode() { return id; } @Override public boolean equals(Object obj) { if (!(obj instanceof Bar)) { return false; } return ((Bar) obj).id == id; } } // for [databind#1002] @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class") @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "uri") static class Element { public URI uri; public String name; @Override public boolean equals(Object object) { if (object == this) { return true; } else if (object == null || !(object instanceof Element)) { return false; } else { Element element = (Element) object; if (element.uri.toString().equalsIgnoreCase(this.uri.toString())) { return true; } } return false; } @Override public int hashCode() { return uri.hashCode(); } } /* /****************************************************** /* Test methods /****************************************************** */ public void testSimpleEquals() throws Exception { ObjectMapper mapper = new ObjectMapper(); // Verify default state too assertFalse(mapper.isEnabled(SerializationFeature.USE_EQUALITY_FOR_OBJECT_ID)); mapper.enable(SerializationFeature.USE_EQUALITY_FOR_OBJECT_ID); Foo foo = new Foo(1); Bar bar1 = new Bar(1); Bar bar2 = new Bar(2); // this is another bar which is supposed to be "equal" to bar1 // due to the same ID and // Bar class' equals() method will return true. Bar anotherBar1 = new Bar(1); foo.bars.add(bar1); foo.bars.add(bar2); // this anotherBar1 object will confuse the serializer. foo.otherBars.add(anotherBar1); foo.otherBars.add(bar2); String json = mapper.writeValueAsString(foo); assertEquals("{\"id\":1,\"bars\":[{\"id\":1},{\"id\":2}],\"otherBars\":[1,2]}", json); Foo foo2 = mapper.readValue(json, Foo.class); assertNotNull(foo2); assertEquals(foo.id, foo2.id); } public void testEqualObjectIdsExternal() throws Exception { Element element = new Element(); element.uri = URI.create("URI"); element.name = "Element1"; Element element2 = new Element(); element2.uri = URI.create("URI"); element2.name = "Element2"; // 12-Nov-2015, tatu: array works fine regardless of Type Erasure, but if using List, // must provide additional piece of type info // Element[] input = new Element[] { element, element2 }; List<Element> input = Arrays.asList(element, element2); ObjectMapper mapper = new ObjectMapper(); mapper.enable(SerializationFeature.USE_EQUALITY_FOR_OBJECT_ID); // String json = mapper.writeValueAsString(input); String json = mapper.writerFor(new TypeReference<List<Element>>() { }) .writeValueAsString(input); Element[] output = mapper.readValue(json, Element[].class); assertNotNull(output); assertEquals(2, output.length); } }