Skip to content

Commit 3747246

Browse files
committed
Fix serialization of referentially equal objects.
Fix #50
1 parent 3909528 commit 3747246

File tree

3 files changed

+25
-5
lines changed

3 files changed

+25
-5
lines changed

json/src/main/java/org/teavm/flavour/json/emit/JsonSerializerEmitter.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,9 @@ private Value<JsonSerializer> emitClassSerializer(ReflectClass<?> cls) {
186186
emitIdentity(information, value, context, target);
187187
emitProperties(information, value, context, target);
188188
Value<? extends Node> result = emitInheritance(information, target);
189+
if (information.idGenerator == IdGeneratorType.NONE) {
190+
emit(() -> context.get().release(value.get()));
191+
}
189192
exit(() -> result.get());
190193
});
191194
}
@@ -217,7 +220,7 @@ private void emitIdentity(ClassInformation information, Value<Object> value,
217220
Value<JsonSerializerContext> context, Value<ObjectNode> target) {
218221
switch (information.idGenerator) {
219222
case NONE:
220-
emit(() -> context.get().touch(value.get()));
223+
emit(() -> context.get().lock(value.get()));
221224
break;
222225
case INTEGER:
223226
emitIntegerIdentity(information, value, context, target);

json/src/main/java/org/teavm/flavour/json/serializer/JsonSerializerContext.java

+8-4
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
public class JsonSerializerContext {
2424
private int lastId;
2525
private Map<Object, Integer> ids = new IdentityHashMap<>();
26-
private Set<Object> touchedObjects = Collections.newSetFromMap(new IdentityHashMap<>());
26+
private Set<Object> lockedObjects = Collections.newSetFromMap(new IdentityHashMap<>());
2727

2828
public boolean hasId(Object object) {
2929
return ids.containsKey(object);
@@ -38,10 +38,14 @@ public int getId(Object object) {
3838
return id;
3939
}
4040

41-
public void touch(Object object) {
42-
if (touchedObjects.contains(object)) {
41+
public void lock(Object object) {
42+
if (lockedObjects.contains(object)) {
4343
throw new IllegalArgumentException("Object has already been serialized: " + object);
4444
}
45-
touchedObjects.add(object);
45+
lockedObjects.add(object);
46+
}
47+
48+
public void release(Object object) {
49+
lockedObjects.remove(object);
4650
}
4751
}

json/src/test/java/org/teavm/flavour/json/test/SerializerTest.java

+13
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import com.fasterxml.jackson.databind.JsonNode;
3838
import com.fasterxml.jackson.databind.node.ArrayNode;
3939
import com.fasterxml.jackson.databind.node.NullNode;
40+
import com.fasterxml.jackson.databind.node.NumericNode;
4041
import java.math.BigDecimal;
4142
import java.math.BigInteger;
4243
import java.util.ArrayList;
@@ -484,6 +485,18 @@ public void abstractSuperclass() {
484485
assertEquals("Unexpected root[1].baz", 4, node.get(1).get("baz").asInt());
485486
}
486487

488+
@Test
489+
public void sameObjectInArray() {
490+
A a = new A();
491+
A[] array = { a, a };
492+
JsonNode node = JSONRunner.serialize(array);
493+
assertEquals(2, node.size());
494+
assertTrue(node.get(0).get("a") instanceof NullNode);
495+
assertTrue(node.get(1).get("a") instanceof NullNode);
496+
assertEquals(0, node.get(0).get("b").intValue());
497+
assertEquals(0, node.get(1).get("b").intValue());
498+
}
499+
487500
@JsonPersistable
488501
public static class A {
489502
private String a;

0 commit comments

Comments
 (0)