代码之家  ›  专栏  ›  技术社区  ›  Frank Kong

jackson jsondersializer堆栈溢出

  •  1
  • Frank Kong  · 技术社区  · 6 年前

    我试图从Java中的json标记中提取属性,并编写jsondeserizer来完成这项工作。
    我的尝试如下:

    public class testJacksonSimple {
        @JsonDeserialize(using = ItemDeserializerJson.class)
        public static class Item {
            public int id;
            public String itemName;
    
            public Item(){};
            public Item(int id, String itemName) {
                this.id = id;
                this.itemName = itemName;
            }
    
            public void setId(int id) {
                this.id = id;
            }
    
            public int getId() {
                return id;
            }
        }
    
        public static class ItemDeserializerJson extends JsonDeserializer<Item> {
    
            ObjectReader reader = new ObjectMapper().reader();
    
            @Override
            public Item deserialize(JsonParser jp, DeserializationContext context) throws IOException {
                if(jp.currentToken() != JsonToken.VALUE_NULL) {
                    return reader.readValue(jp, Item.class);
                } else {
                    return null;
                }
            }
        }
    }
    

    这是我的测试用例:

    public class test {
        public static void main(String[] args){
            ObjectMapper mapper = new ObjectMapper();
            String json = "{\n" +
                    "    \"id\": 1,\n" +
                    "    \"itemName\": \"theItem\"\n" +
                    "}";
            System.out.println(json);
            testJacksonSimple.Item itemWithOwner = null;
            try {
                itemWithOwner = new ObjectMapper().readValue(json, testJacksonSimple.Item.class);
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println(itemWithOwner.id);
            System.out.println(itemWithOwner.itemName);
        }
    }
    

    我搞错了:

    Exception in thread "main" java.lang.StackOverflowError
        at java.lang.reflect.Method.getParameterTypes(Method.java:264)
        at sun.reflect.annotation.AnnotationInvocationHandler.invoke(AnnotationInvocationHandler.java:59)
        at com.sun.proxy.$Proxy2.annotationType(Unknown Source)
        at com.fasterxml.jackson.databind.introspect.AnnotationMap._add(AnnotationMap.java:135)
        at com.fasterxml.jackson.databind.introspect.AnnotationMap.addIfNotPresent(AnnotationMap.java:101)
        at com.fasterxml.jackson.databind.introspect.AnnotatedClass._addAnnotationsIfNotPresent(AnnotatedClass.java:1061)
        at com.fasterxml.jackson.databind.introspect.AnnotatedClass._resolveClassAnnotations(AnnotatedClass.java:399)
        at com.fasterxml.jackson.databind.introspect.AnnotatedClass._classAnnotations(AnnotatedClass.java:376)
        at com.fasterxml.jackson.databind.introspect.AnnotatedClass.getAnnotation(AnnotatedClass.java:248)
        at com.fasterxml.jackson.databind.AnnotationIntrospector._findAnnotation(AnnotationIntrospector.java:1436)
        at com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector.findAutoDetectVisibility(JacksonAnnotationIntrospector.java:349)
        at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.<init>(POJOPropertiesCollector.java:129)
    

    只是不明白为什么我得到错误堆栈溢出。我可以不使用自定义jsondersializer获得正确的结果,但我想测试它。如有任何帮助,我们将不胜感激。

    2 回复  |  直到 6 年前
        1
  •  3
  •   Justin.Cooke    6 年前

    通过调用objectmapper并请求它从自定义反序列化程序内部反序列化json,您创建了一个无限循环。对象映射器正在调用自定义反序列化程序,然后自定义反序列化程序正在调用对象映射器。因此堆栈溢出。

    以下对我有效:

        public static class ItemDeserializerJson extends JsonDeserializer<Item> {
    
        @Override
        public Item deserialize(JsonParser jp, DeserializationContext context) throws IOException {
    
            JsonNode node = jp.getCodec().readTree(jp);
            int id = (Integer) (node.get("id")).numberValue();
            String itemName = node.get("itemName").asText();
    
            return new Item(id, itemName);
        }
    }
    
        2
  •  0
  •   standy    6 年前

    所以基本上 reader.readValue(jp, Item.class); 将重复调用反序列化方法。 顺便说一下,请遵守命名约定(类名应该是大写的camelcase): http://www.oracle.com/technetwork/java/javase/overview/codeconventions-135099.html