2014-11-20 87 views
0

我想反序列化使用杰克逊现有的JSON文件,并想知道是否有可能执行下面的翻译,而不诉诸一堆自定义反序列化。杰克逊阵列元素POJO

输入JSON看起来是这样的:

{ 
    "type": "foo", 
    "content": ["a", "b", {"some": "object", "goes": "here"}, 4] 
} 

第3个content元素不改变,总是字符串,字符串,SomeDataStructure,整型(可选)

而且我想反序列化到这样的事情:

class Foo { 
    public static class FooContent { 
     String some; 
     String goes; 
    } 

    String aString; 
    String bString; 
    FooContent content; 
    Integer cInt;  
} 

现在我已经遇到BeanAsArrayDeserializer,这听起来喜欢它可能是我想要的,但我似乎无法找到任何东西,甚至像一段示例代码,让我开始。

那么,有什么想法?

回答

0

您始终可以实现您的自定义解串器。请参见下面的源代码:

import java.io.IOException; 

import com.fasterxml.jackson.core.JsonParser; 
import com.fasterxml.jackson.core.JsonProcessingException; 
import com.fasterxml.jackson.core.JsonToken; 
import com.fasterxml.jackson.databind.DeserializationContext; 
import com.fasterxml.jackson.databind.JsonDeserializer; 
import com.fasterxml.jackson.databind.ObjectMapper; 
import com.fasterxml.jackson.databind.SerializationFeature; 
import com.fasterxml.jackson.databind.annotation.JsonDeserialize; 

; 

public class JacksonTest { 

    public static void main(String[] args) throws Exception { 
     String json = "{\"type\": \"foo\",\"content\": [\"a\", \"b\", {\"some\": \"object\", \"goes\": \"here\"}, 4]}"; 

     ObjectMapper mapper = new ObjectMapper(); 
     mapper.configure(SerializationFeature.INDENT_OUTPUT, true); 
     mapper.configure(SerializationFeature.WRITE_EMPTY_JSON_ARRAYS, true); 

     Root pojo = mapper.readValue(json, Root.class); 
     System.out.println(pojo); 
    } 
} 

class Root { 
    public String type; 
    @JsonDeserialize(using = FooDeserializer.class) 
    public Foo content; 

    @Override 
    public String toString() { 
     return content.toString(); 
    } 
} 

class Foo { 
    public static class FooContent { 
     public String some; 
     public String goes; 

     @Override 
     public String toString() { 
      return "{" + some + ", " + goes + "}"; 
     } 
    } 

    String aString; 
    String bString; 
    FooContent content; 
    Integer cInt; 

    @Override 
    public String toString() { 
     return "Foo [aString=" + aString + ", bString=" + bString + ", content=" + content 
       + ", cInt=" + cInt + "]"; 
    } 
} 

class FooDeserializer extends JsonDeserializer<Foo> { 

    @Override 
    public Foo deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, 
      JsonProcessingException { 
     Foo f = new Foo(); 
     int index = 0; 
     while (jp.nextToken() != JsonToken.END_ARRAY) { 
      JsonToken token = jp.getCurrentToken(); 
      if (token.isStructStart()) { 
       f.content = jp.readValueAs(Foo.FooContent.class); 
       index++; 
      } else { 
       switch (index++) { 
       case 0: 
        f.aString = jp.getText(); 
        break; 
       case 1: 
        f.bString = jp.getText(); 
        break; 
       case 3: 
        f.cInt = Integer.parseInt(jp.getText()); 
        break; 
       } 
      } 
     } 
     return f; 
    } 
} 

以上应用程序打印:

Foo [aString=a, bString=b, content={object, here}, cInt=4] 
+0

Nice code snippet Michal。看起来它只适用于单深度数组。你碰巧知道一个跟踪嵌套数组索引而不用某种类型的字典来跟踪数组/对象深度的简单方法吗?一直在想这个问题一段时间,领导可能会有所帮助。 – Conor 2015-10-28 22:42:07

+0

以上代码是仅适用于上述数据结构的自定义实现。如果我们想要编写更通用的解决方案,我们必须编写新的阵列解串器,并尝试配置它并为属性添加索引。 (反序列化器必须知道会发生什么)。您可以使用示例'JSON'和'POJO'结构在SO上创建新问题。 – 2015-10-29 17:48:03

0

该功能允许使用BeanAsArrayDeserializer(内部)是@JsonFormat。您可以在this博客文章中阅读关于它的一些信息。

我也刚刚了解到它,但我认为适用于您的案例的映射看起来如下所示。你需要一个包装器来保存content字段,然后它将是Foo类型。

@JsonFormat(shape = Shape.ARRAY) 
@JsonPropertyOrder({ "aString", "bString, "content", "cInt }) 
class Foo { 
    public static class FooContent { 
     String some; 
     String goes; 
    } 

    @JsonFormat(shape = Shape.STRING) 
    String aString; 

    @JsonFormat(shape = Shape.STRING) 
    String bString; 

    FooContent content; 

    @JsonFormat(shape = Shape.NUMBER) 
    Integer cInt;  
}