diff --git a/jr-objects/src/main/java/tools/jackson/jr/ob/impl/ValueWriterLocator.java b/jr-objects/src/main/java/tools/jackson/jr/ob/impl/ValueWriterLocator.java index 3ef707ac..f23d63a9 100644 --- a/jr-objects/src/main/java/tools/jackson/jr/ob/impl/ValueWriterLocator.java +++ b/jr-objects/src/main/java/tools/jackson/jr/ob/impl/ValueWriterLocator.java @@ -309,6 +309,27 @@ protected BeanPropertyWriter[] _resolveBeanForSer(Class raw, POJODefinition b f.setAccessible(true); } } + // NOTE: cannot just call `findSerializationType()` due to + // cyclic type definitions. + + int typeId; + Integer I = _knownSerTypes.get(new ClassKey(type, _features)); + + if (I != null) { + typeId = I.intValue(); + } else { + typeId = _findSimpleType(type, true); + if ((_writerModifier != null) && typeId != 0) { + ValueWriter w = _writerModifier.overrideStandardValueWriter(_writeContext, type, typeId); + if (w != null) { + typeId = _registerWriter(type, w); + } + } + // But what if none found? Discovered dynamically later on? + } + + // 16-Feb-2024, tatu: Code pre-2.17 -- remove from 2.18 if not needed + /* int typeId = _findSimpleType(type, true); // Give plugin the opportunity to override standard value writer if (_writerModifier != null && typeId != 0) { @@ -318,8 +339,11 @@ protected BeanPropertyWriter[] _resolveBeanForSer(Class raw, POJODefinition b if (w != null) { typeId = _registerWriter(type, w); } + } else { + typeId = I.intValue(); } } + */ props.add(new BeanPropertyWriter(typeId, rawProp.name, rawProp.field, m)); } int plen = props.size(); diff --git a/jr-objects/src/test/java/tools/jackson/jr/ob/WriteBeansTest.java b/jr-objects/src/test/java/tools/jackson/jr/ob/WriteBeansTest.java index 6c40db0f..131b165f 100644 --- a/jr-objects/src/test/java/tools/jackson/jr/ob/WriteBeansTest.java +++ b/jr-objects/src/test/java/tools/jackson/jr/ob/WriteBeansTest.java @@ -55,6 +55,24 @@ public StringBeanBean(StringBean b) { bean = b; } } + + static class TreeNodeBean { + public int id; + public String name; + + public TreeNodeBean nextLeft, nextRight; + + public TreeNodeBean(int id, String name) { + this.id = id; + this.name = name; + } + } + + /* + /********************************************************************** + /* Test methods + /********************************************************************** + */ public void testBinary() throws Exception { @@ -128,4 +146,19 @@ public void testBeanNulls() throws Exception assertEquals(a2q("{'bean':{'value':null}}"), withNulls.asString(new StringBeanBean(new StringBean(null)))); } + + public void testBeanWithRecursiveType() throws Exception + { + TreeNodeBean root = new TreeNodeBean(1, "root"); + TreeNodeBean left = new TreeNodeBean(2, "left"); + TreeNodeBean right = new TreeNodeBean(3, "right"); + root.nextLeft = left; + root.nextRight = right; + + assertEquals(a2q("{'id':1,'name':'root'," + +"'nextLeft':{'id':2,'name':'left'}," + +"'nextRight':{'id':3,'name':'right'}" + +"}"), + JSON.std.asString(root)); + } } diff --git a/jr-objects/src/test/java/tools/jackson/jr/ob/impl/ValueWriterModifier112Test.java b/jr-objects/src/test/java/tools/jackson/jr/ob/impl/ValueWriterModifier112Test.java index 1c9028f7..f553e9c6 100644 --- a/jr-objects/src/test/java/tools/jackson/jr/ob/impl/ValueWriterModifier112Test.java +++ b/jr-objects/src/test/java/tools/jackson/jr/ob/impl/ValueWriterModifier112Test.java @@ -16,6 +16,12 @@ static class TestBean112 { public Path p2; } + static class StringBean112 { + public String s1; + public String s2; + public String s3; + } + static class PathWriter implements ValueWriter { @Override public void writeValue(JSONWriter context, JsonGenerator g, Object value) { @@ -28,24 +34,32 @@ public Class valueType() { } } - // [jackson-jr#112] - public void testMultipleFieldOverrides() throws Exception - { - TestBean112 input = new TestBean112(); - input.p1 = Paths.get("some/path"); - input.p2 = Paths.get("some/other/path"); + static class UpperCaseWriter implements ValueWriter { + @Override + public void writeValue(JSONWriter context, JsonGenerator g, Object value) { + g.writeString(String.valueOf(value).toUpperCase()); + } + + @Override + public Class valueType() { + return String.class; + } + } - JSON writer = JSON.builder() + private final JSON WRITER = JSON.builder() .register(new JacksonJrExtension() { @Override protected void register(ExtensionContext ctxt) { ctxt.insertModifier(new ReaderWriterModifier() { @Override public ValueWriter overrideStandardValueWriter(JSONWriter writeContext, Class type, int stdTypeId) { - if (type == Path.class) { + if (Path.class.isAssignableFrom(type)) { return new PathWriter(); } - return super.overrideStandardValueWriter(writeContext, type, stdTypeId); + if (type == String.class) { + return new UpperCaseWriter(); + } + return null; } }); ctxt.insertProvider(new ReaderWriterProvider() { @@ -54,12 +68,29 @@ public ValueWriter findValueWriter(JSONWriter writeContext, Class type) { if (Path.class.isAssignableFrom(type)) { return new PathWriter(); } - return super.findValueWriter(writeContext, type); + return null; } }); } }).build(); - String json = writer.asString(input); + + // [jackson-jr#112] + public void testMultipleFieldOverrides() throws Exception + { + TestBean112 input = new TestBean112(); + input.p1 = Paths.get("some/path"); + input.p2 = Paths.get("some/other/path"); + String json = WRITER.asString(input); assertEquals(a2q("{'p1':'some\\/path','p2':'some\\/other\\/path'}"), json); } + + public void testMultipleStringFieldOverrides() throws Exception + { + StringBean112 input = new StringBean112(); + input.s1 = "abc"; + input.s2 = "def"; + input.s3 = "g"; + String json = WRITER.asString(input); + assertEquals(a2q("{'s1':'ABC','s2':'DEF','s3':'G'}"), json); + } } diff --git a/jr-objects/src/test/java/tools/jackson/jr/ob/impl/ValueWriterModifierTest.java b/jr-objects/src/test/java/tools/jackson/jr/ob/impl/ValueWriterModifierTest.java index 829a5023..ae99fa97 100644 --- a/jr-objects/src/test/java/tools/jackson/jr/ob/impl/ValueWriterModifierTest.java +++ b/jr-objects/src/test/java/tools/jackson/jr/ob/impl/ValueWriterModifierTest.java @@ -110,8 +110,12 @@ public Class valueType() { assertEquals(quote("foobar"), JSON.std.asString(input)); // And then also applicable for multiple POJO properties - assertEquals(a2q("{'first':'Bob','last':'Hope'}"), + assertEquals(a2q("{'first':'BOB','last':'HOPE'}"), jsonWithMod.asString(new Name("Bob", "Hope"))); + + // .. and not global standard variant + assertEquals(a2q("{'first':'Bob','last':'Hope'}"), + JSON.std.asString(new Name("Bob", "Hope"))); } public void testPOJOWriterReplacement() throws Exception