diff --git a/src/changes/changes.xml b/src/changes/changes.xml index b5f9ce05..7cfbbc30 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -34,6 +34,11 @@ Potentially incompatible change: The standard and referencing binary formats now support null as a map key. + + Potentially incompatible change: + The referencing binary format no longer deduplicates collections. + The old format can still be parsed successfully. + Potentially incompatible change: The standard binary and simple JSON formats now handle `Iterable` as a collection type. @@ -44,7 +49,7 @@ Instead of a Joda-Convert formatted string, the array is output as a list of primitives. This also applies to multi-dimensional arrays. This is a much more natural JSON format. - The old format cam still be parsed successfully. + The old format can still be parsed successfully. Incompatible change: @@ -52,7 +57,7 @@ For example, where the type of the collection is Object, previously a String value was explicitly typed as a String, now the type is implicit. This is a much more natural JSON format. - The old format cam still be parsed successfully. + The old format can still be parsed successfully. Incompatible change: diff --git a/src/main/java/org/joda/beans/ser/bin/BeanReferences.java b/src/main/java/org/joda/beans/ser/bin/BeanReferences.java index fb38cb3b..b86cd781 100644 --- a/src/main/java/org/joda/beans/ser/bin/BeanReferences.java +++ b/src/main/java/org/joda/beans/ser/bin/BeanReferences.java @@ -133,11 +133,16 @@ private void findReferencesBean( } // has this object been seen before, if so no need to check it again - var result = objects.compute(base, BeanReferences::incrementOrOne); - if (result > 1) { + if (objects.compute(base, BeanReferences::incrementOrOne) > 1) { + // shouldn't try and reuse references to collections + if (!(base instanceof Bean) && parentIterator != null) { + var childIterator = settings.getIteratorFactory().createChild(base, parentIterator); + if (childIterator != null) { + findReferencesIterable(childIterator, objects); + } + } return; } - if (base instanceof Bean bean) { addClassInfo(base, declaredClass); if (settings.getConverter().isConvertible(bean.getClass())) { @@ -165,6 +170,7 @@ private void findReferencesBean( } else if (parentIterator != null) { var childIterator = settings.getIteratorFactory().createChild(base, parentIterator); if (childIterator != null) { + // shouldn't try and reuse references to collections findReferencesIterable(childIterator, objects); } else { addClassInfo(base, declaredClass); diff --git a/src/test/java/org/joda/beans/ser/SerTestHelper.java b/src/test/java/org/joda/beans/ser/SerTestHelper.java index 5f8b400d..659c08a6 100644 --- a/src/test/java/org/joda/beans/ser/SerTestHelper.java +++ b/src/test/java/org/joda/beans/ser/SerTestHelper.java @@ -19,10 +19,12 @@ import java.util.Currency; import java.util.EnumSet; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.TimeZone; +import java.util.TreeSet; import org.joda.beans.sample.Address; import org.joda.beans.sample.Company; @@ -256,6 +258,17 @@ public static ImmGenericCollections testGenericInterfaces( .build(); } + public static ImmGenericCollections testGenericInterfacesCollections() { + return ImmGenericCollections.builder() + .map(ImmutableMap.of( + "First", Arrays.asList("A", "B"), + "First1", ImmutableList.of("A", "B"), + "Third1", new TreeSet<>(ImmutableList.of("A", "B")), + "Third", new HashSet<>(Arrays.asList("A", "B")), + "Second", testCollections(true))) + .build(); + } + public static ImmKeyList testIntermediateInterfaces() { // second serialized as JodaConvertInterface, non-bean // third and fourth are serialized as an intermediate Joda-Convert interface INamedKey diff --git a/src/test/java/org/joda/beans/ser/bin/TestSerializeReferencingBin.java b/src/test/java/org/joda/beans/ser/bin/TestSerializeReferencingBin.java index 85951380..34825bba 100644 --- a/src/test/java/org/joda/beans/ser/bin/TestSerializeReferencingBin.java +++ b/src/test/java/org/joda/beans/ser/bin/TestSerializeReferencingBin.java @@ -130,6 +130,17 @@ void test_writeJodaConvertInterface() { BeanAssert.assertBeanEquals(bean, parsed); } + @Test + void test_writeJodaConvertInterfaceCollections() { + var bean = SerTestHelper.testGenericInterfacesCollections(); + + var bytes = JodaBeanSer.COMPACT.binWriterReferencing().write(bean); +// System.out.println(JodaBeanBinReader.visualize(bytes)); + + var parsed = JodaBeanSer.COMPACT.binReader().read(bytes); + BeanAssert.assertBeanEquals(parsed, bean); + } + @Test void test_writeIntermediateInterface() { var bean = SerTestHelper.testIntermediateInterfaces();