This is an automated email from the ASF dual-hosted git repository.

heneveld pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/brooklyn-server.git


The following commit(s) were added to refs/heads/master by this push:
     new 0a8f536  better support for deserializing list types
0a8f536 is described below

commit 0a8f5369805a0cc14392ba868f17e826e5edc732
Author: Alex Heneveld <[email protected]>
AuthorDate: Thu Jan 21 22:54:47 2021 +0000

    better support for deserializing list types
---
 .../resolve/jackson/AsPropertyIfAmbiguous.java     | 51 +++++++++++++++++++++-
 ...BrooklynRegisteredTypeJacksonSerialization.java |  7 ++-
 ...klynRegisteredTypeJacksonSerializationTest.java | 27 ++++++++++++
 .../core/resolve/jackson/MapperTestFixture.java    |  9 ++++
 4 files changed, 91 insertions(+), 3 deletions(-)

diff --git 
a/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/AsPropertyIfAmbiguous.java
 
b/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/AsPropertyIfAmbiguous.java
index 2cd99b8..26fc860 100644
--- 
a/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/AsPropertyIfAmbiguous.java
+++ 
b/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/AsPropertyIfAmbiguous.java
@@ -23,6 +23,7 @@ import com.fasterxml.jackson.core.JsonGenerator;
 import com.fasterxml.jackson.core.JsonParser;
 import com.fasterxml.jackson.core.JsonToken;
 import com.fasterxml.jackson.core.type.WritableTypeId;
+import com.fasterxml.jackson.core.util.JsonParserSequence;
 import com.fasterxml.jackson.databind.BeanProperty;
 import com.fasterxml.jackson.databind.DeserializationContext;
 import com.fasterxml.jackson.databind.JavaType;
@@ -32,7 +33,9 @@ import com.fasterxml.jackson.databind.jsontype.TypeIdResolver;
 import com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer;
 import com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeSerializer;
 import com.fasterxml.jackson.databind.util.TokenBuffer;
+import java.util.function.Supplier;
 import 
org.apache.brooklyn.core.resolve.jackson.AsPropertyIfAmbiguous.HasBaseType;
+import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.javalang.Reflections;
 
 import java.io.IOException;
@@ -131,7 +134,6 @@ public class AsPropertyIfAmbiguous {
                     return delegate.deserializeTypedFromObject(p, ctxt);
                 }
             }
-
             return super.deserializeTypedFromObject(p, ctxt);
         }
 
@@ -141,6 +143,7 @@ public class AsPropertyIfAmbiguous {
         }
 
         // deserialize list-like things
+        @Override
         protected Object _deserialize(JsonParser p, DeserializationContext 
ctxt) throws IOException {
             if (p.isExpectedStartArrayToken()) {
                 // when we suppress types for collections, the deserializer
@@ -150,7 +153,7 @@ public class AsPropertyIfAmbiguous {
                 JsonDeserializer<Object> deser = _findDeserializer(ctxt, 
typeId);
 
                 if (p.currentToken() == JsonToken.END_ARRAY) {
-                    return deser.getNullValue(ctxt);
+                    return deser.getEmptyValue(ctxt);
                 }
                 return deser.deserialize(p, ctxt);
             } else {
@@ -158,5 +161,49 @@ public class AsPropertyIfAmbiguous {
             }
         }
 
+        @Override
+        protected Object _deserializeTypedForId(JsonParser p, 
DeserializationContext ctxt,
+                                                TokenBuffer tb) throws 
IOException
+        {
+            // first part copied from parent
+
+            String typeId = p.getText();
+            JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId);
+            if (_typeIdVisible) { // need to merge id back in JSON input?
+                if (tb == null) {
+                    tb = new TokenBuffer(p, ctxt);
+                }
+                tb.writeFieldName(p.getCurrentName());
+                tb.writeString(typeId);
+            }
+            if (tb != null) { // need to put back skipped properties?
+                // 02-Jul-2016, tatu: Depending on for JsonParserSequence is 
initialized it may
+                //   try to access current token; ensure there isn't one
+                p.clearCurrentToken();
+                p = JsonParserSequence.createFlattened(false, tb.asParser(p), 
p);
+            }
+            // Must point to the next value; tb had no current, jp pointed to 
VALUE_STRING:
+            p.nextToken(); // to skip past String value
+            // deserializer should take care of closing END_OBJECT as well
+
+            boolean wasEndToken = (p.currentToken() == JsonToken.END_OBJECT);
+            try {
+                return deser.deserialize(p, ctxt);
+            } catch (Exception e) {
+                Exceptions.propagateIfFatal(e);
+                if (wasEndToken) {
+                    // new -- we allow e.g. `{ type: list-extended }` to mean 
it is a list;
+                    // however the only way to set values for it in the same 
object would be to define a custom deserializer for it;
+                    // normal use case is that context implies e.g. 
list-extended, then collection deserializer does the right thing when it is 
used.
+                    // but if we got an empty map somehow, e.g. user supplied, 
don't use it.
+                    Object candidate = deser.getEmptyValue(ctxt);
+                    if (candidate!=null) {
+                        return candidate;
+                    }
+                }
+                throw e;
+            }
+        }
+
     }
 }
\ No newline at end of file
diff --git 
a/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/BrooklynRegisteredTypeJacksonSerialization.java
 
b/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/BrooklynRegisteredTypeJacksonSerialization.java
index 507f93c..e9724c8 100644
--- 
a/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/BrooklynRegisteredTypeJacksonSerialization.java
+++ 
b/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/BrooklynRegisteredTypeJacksonSerialization.java
@@ -59,7 +59,7 @@ public class BrooklynRegisteredTypeJacksonSerialization {
         @Override
         public T deserialize(JsonParser p, DeserializationContext ctxt) throws 
IOException, JsonProcessingException {
             try {
-                Object target = 
mgmt.getTypeRegistry().createBean(type.getRegisteredType(), null, null);
+                Object target = getEmptyValue(ctxt);
                 JsonDeserializer<Object> delegate = 
ctxt.findContextualValueDeserializer(ctxt.constructType(target.getClass()), 
null);
                 delegate.deserialize(p, ctxt, target);
                 return (T)target;
@@ -67,6 +67,11 @@ public class BrooklynRegisteredTypeJacksonSerialization {
                 throw Exceptions.propagate(e);
             }
         }
+
+        public Object getEmptyValue(DeserializationContext ctxt) throws 
JsonMappingException {
+            // empty for us is the underlying definition, not null
+            return mgmt.getTypeRegistry().createBean(type.getRegisteredType(), 
null, null);
+        }
     }
 
     static class RegisteredTypeDeserializers extends SimpleDeserializers {
diff --git 
a/core/src/test/java/org/apache/brooklyn/core/resolve/jackson/BrooklynRegisteredTypeJacksonSerializationTest.java
 
b/core/src/test/java/org/apache/brooklyn/core/resolve/jackson/BrooklynRegisteredTypeJacksonSerializationTest.java
index 0dc9fd7..af56d66 100644
--- 
a/core/src/test/java/org/apache/brooklyn/core/resolve/jackson/BrooklynRegisteredTypeJacksonSerializationTest.java
+++ 
b/core/src/test/java/org/apache/brooklyn/core/resolve/jackson/BrooklynRegisteredTypeJacksonSerializationTest.java
@@ -26,6 +26,7 @@ import 
org.apache.brooklyn.core.typereg.BasicTypeImplementationPlan;
 import org.apache.brooklyn.core.typereg.JavaClassNameTypePlanTransformer;
 import org.apache.brooklyn.core.typereg.RegisteredTypes;
 import org.apache.brooklyn.test.Asserts;
+import org.apache.brooklyn.util.collections.MutableList;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
@@ -92,4 +93,30 @@ public class BrooklynRegisteredTypeJacksonSerializationTest 
extends BrooklynMgmt
         Asserts.assertEquals(((SampleBean)impl).z, "zzz");
     }
 
+    static class ListExtended extends MutableList<String> {
+    }
+
+    @Test
+    public void testExtendedListBeanRegisteredType() throws Exception {
+        RegisteredType rt = RegisteredTypes.bean("list-extended", "1",
+                new BasicTypeImplementationPlan(BeanWithTypeUtils.FORMAT,
+                        "type: " + ListExtended.class.getName()
+                ));
+        
((BasicBrooklynTypeRegistry)mgmt().getTypeRegistry()).addToLocalUnpersistedTypeRegistry(rt,
 false);
+
+        Object impl = mgmt().getTypeRegistry().create(rt, null, null);
+        Asserts.assertInstanceOf(impl, ListExtended.class);
+
+        impl = 
mgmt().getTypeRegistry().createBeanFromPlan(BeanWithTypePlanTransformer.FORMAT,
+                "type: list-extended"
+                , null, null);
+        Assert.assertTrue( ((ListExtended)impl).isEmpty() );
+
+        Object impl2 = deser("[]", rt);
+        Assert.assertTrue( ((ListExtended)impl2).isEmpty() );
+
+        Object impl3 = deser("[3]", rt);
+        Assert.assertEquals( ((ListExtended)impl3).size(), 1 );
+    }
+
 }
diff --git 
a/core/src/test/java/org/apache/brooklyn/core/resolve/jackson/MapperTestFixture.java
 
b/core/src/test/java/org/apache/brooklyn/core/resolve/jackson/MapperTestFixture.java
index ecacdfd..c92ef37 100644
--- 
a/core/src/test/java/org/apache/brooklyn/core/resolve/jackson/MapperTestFixture.java
+++ 
b/core/src/test/java/org/apache/brooklyn/core/resolve/jackson/MapperTestFixture.java
@@ -21,6 +21,7 @@ package org.apache.brooklyn.core.resolve.jackson;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.common.collect.Iterables;
+import org.apache.brooklyn.api.typereg.RegisteredType;
 import org.apache.brooklyn.util.core.task.BasicExecutionContext;
 import org.apache.brooklyn.util.core.task.BasicExecutionManager;
 import org.apache.brooklyn.util.core.task.Tasks;
@@ -53,6 +54,14 @@ public interface MapperTestFixture {
         }
     }
 
+    default <T> T deser(String v, RegisteredType type) {
+        try {
+            return mapper().readValue(v, BrooklynJacksonType.of(type));
+        } catch (JsonProcessingException e) {
+            throw Exceptions.propagate(e);
+        }
+    }
+
     default <T> T deser(String v) {
         return (T) deser(v, Object.class);
     }

Reply via email to