1 package com.fasterxml.jackson.databind.objectid; 2 3 import java.net.URI; 4 import java.util.*; 5 6 import com.fasterxml.jackson.annotation.*; 7 import com.fasterxml.jackson.core.type.TypeReference; 8 import com.fasterxml.jackson.databind.*; 9 10 public class TestObjectIdWithEquals extends BaseMapTest 11 { 12 @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id", scope=Foo.class) 13 static class Foo { 14 public int id; 15 16 public List<Bar> bars = new ArrayList<Bar>(); 17 public List<Bar> otherBars = new ArrayList<Bar>(); 18 Foo()19 public Foo() { } Foo(int i)20 public Foo(int i) { id = i; } 21 } 22 23 @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id", scope=Bar.class) 24 static class Bar 25 { 26 public int id; 27 Bar()28 public Bar() { } Bar(int i)29 public Bar(int i) { 30 id = i; 31 } 32 33 @Override hashCode()34 public int hashCode() { 35 return id; 36 } 37 38 @Override equals(Object obj)39 public boolean equals(Object obj) { 40 if (!(obj instanceof Bar)) { 41 return false; 42 } 43 return ((Bar) obj).id == id; 44 } 45 } 46 47 // for [databind#1002] 48 @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class") 49 @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "uri") 50 static class Element { 51 public URI uri; 52 public String name; 53 54 @Override equals(Object object)55 public boolean equals(Object object) { 56 if (object == this) { 57 return true; 58 } else if (object == null || !(object instanceof Element)) { 59 return false; 60 } else { 61 Element element = (Element) object; 62 if (element.uri.toString().equalsIgnoreCase(this.uri.toString())) { 63 return true; 64 } 65 } 66 return false; 67 } 68 69 @Override hashCode()70 public int hashCode() { 71 return uri.hashCode(); 72 } 73 } 74 75 /* 76 /****************************************************** 77 /* Test methods 78 /****************************************************** 79 */ 80 testSimpleEquals()81 public void testSimpleEquals() throws Exception 82 { 83 ObjectMapper mapper = new ObjectMapper(); 84 // Verify default state too 85 assertFalse(mapper.isEnabled(SerializationFeature.USE_EQUALITY_FOR_OBJECT_ID)); 86 mapper.enable(SerializationFeature.USE_EQUALITY_FOR_OBJECT_ID); 87 88 Foo foo = new Foo(1); 89 90 Bar bar1 = new Bar(1); 91 Bar bar2 = new Bar(2); 92 // this is another bar which is supposed to be "equal" to bar1 93 // due to the same ID and 94 // Bar class' equals() method will return true. 95 Bar anotherBar1 = new Bar(1); 96 97 foo.bars.add(bar1); 98 foo.bars.add(bar2); 99 // this anotherBar1 object will confuse the serializer. 100 foo.otherBars.add(anotherBar1); 101 foo.otherBars.add(bar2); 102 103 String json = mapper.writeValueAsString(foo); 104 assertEquals("{\"id\":1,\"bars\":[{\"id\":1},{\"id\":2}],\"otherBars\":[1,2]}", json); 105 106 Foo foo2 = mapper.readValue(json, Foo.class); 107 assertNotNull(foo2); 108 assertEquals(foo.id, foo2.id); 109 } 110 testEqualObjectIdsExternal()111 public void testEqualObjectIdsExternal() throws Exception 112 { 113 Element element = new Element(); 114 element.uri = URI.create("URI"); 115 element.name = "Element1"; 116 117 Element element2 = new Element(); 118 element2.uri = URI.create("URI"); 119 element2.name = "Element2"; 120 121 // 12-Nov-2015, tatu: array works fine regardless of Type Erasure, but if using List, 122 // must provide additional piece of type info 123 // Element[] input = new Element[] { element, element2 }; 124 List<Element> input = Arrays.asList(element, element2); 125 126 ObjectMapper mapper = new ObjectMapper(); 127 mapper.enable(SerializationFeature.USE_EQUALITY_FOR_OBJECT_ID); 128 129 // String json = mapper.writeValueAsString(input); 130 String json = mapper.writerFor(new TypeReference<List<Element>>() { }) 131 .writeValueAsString(input); 132 133 Element[] output = mapper.readValue(json, Element[].class); 134 assertNotNull(output); 135 assertEquals(2, output.length); 136 } 137 } 138