【问题标题】:Jackson complex list serializationJackson复杂列表序列化
【发布时间】:2011-12-07 14:26:23
【问题描述】:

我正在使用 Jackson 序列化/反序列化。 例如,我有这样的课程:

class Base{
    String baseId;
}

我想序列化 List objs; 要使用杰克逊,我需要指定列表元素的真实类型,因为 java 类型擦除。 此代码将起作用:

List<Base> data = getData();
return new ObjectMapper().writerWithType(TypeFactory.collectionType(List.class, Base.class)).writeValueAsString(data);

现在,我想序列化更复杂的类:

class Result{
     List<Base> data;
}

我应该如何告诉 Jackson 正确序列化这个类?

【问题讨论】:

  • 注意:不建议在原题的示例代码中使用TypeFactory。相反,使用 mapper.getTypeFactory().constructCollectionType()。
  • 我没有猜到如何将 List 指定为constructCollectionType 参数。这就是我在那里使用 collectionType 的原因。

标签: json serialization jackson


【解决方案1】:

只是

new ObjectMapper().writeValueAsString(myResult);

列表的类型不会因为类型擦除而丢失,就像在第一个示例中一样。


请注意,对于列表或通用列表的普通序列化,没有必要指定列表组件类型,如原始问题中的示例所示。以下所有三个示例序列化都表示具有完全相同 JSON 的 List&lt;Bar&gt;

import java.util.ArrayList;
import java.util.List;

import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility;
import org.codehaus.jackson.annotate.JsonMethod;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.ObjectWriter;

public class JacksonFoo
{
  public static void main(String[] args) throws Exception
  {
    Baz baz = new Baz("BAZ", 42);
    Zab zab = new Zab("ZAB", true);
    List<Bar> bars = new ArrayList<Bar>();
    bars.add(baz);
    bars.add(zab);

    ObjectMapper mapper = new ObjectMapper().setVisibility(JsonMethod.FIELD, Visibility.ANY);

    String json1 = mapper.writeValueAsString(bars);
    System.out.println(json1);
    // output:
    // [{"name":"BAZ","size":42},{"name":"ZAB","hungry":true}]

    Foo foo = new Foo(bars);

    String json2 = mapper.writeValueAsString(foo);
    System.out.println(json2);
    // output:
    // {"bars":[{"name":"BAZ","size":42},{"name":"ZAB","hungry":true}]}

    mapper = new ObjectMapper().setVisibility(JsonMethod.FIELD, Visibility.ANY);
    ObjectWriter typedWriter = mapper.writerWithType(mapper.getTypeFactory().constructCollectionType(List.class, Bar.class));

    String json3 = typedWriter.writeValueAsString(bars);
    System.out.println(json3);
    // output:
    // [{"name":"BAZ","size":42},{"name":"ZAB","hungry":true}]
  }
}

class Foo
{
  List<Bar> bars;
  Foo(List<Bar> b) {bars = b;}
}

abstract class Bar
{
  String name;
  Bar(String n) {name = n;}
}

class Baz extends Bar
{
  int size;
  Baz(String n, int s) {super(n); size = s;}
}

class Zab extends Bar
{
  boolean hungry;
  Zab(String n, boolean h) {super(n); hungry = h;}
}

在使用附加类型信息进行序列化时,类型化编写器很有用。请注意下面的 json1json3 输出有何不同。

import java.util.ArrayList;
import java.util.List;

import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility;
import org.codehaus.jackson.annotate.JsonMethod;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.ObjectMapper.DefaultTyping;
import org.codehaus.jackson.map.ObjectWriter;

public class JacksonFoo
{
  public static void main(String[] args) throws Exception
  {
    Baz baz = new Baz("BAZ", 42);
    Zab zab = new Zab("ZAB", true);
    List<Bar> bars = new ArrayList<Bar>();
    bars.add(baz);
    bars.add(zab);

    ObjectMapper mapper = new ObjectMapper().setVisibility(JsonMethod.FIELD, Visibility.ANY);
    mapper.enableDefaultTypingAsProperty(DefaultTyping.OBJECT_AND_NON_CONCRETE, "type");

    String json1 = mapper.writeValueAsString(bars);
    System.out.println(json1);
    // output:
    // [
    //   {"type":"com.stackoverflow.q8416904.Baz","name":"BAZ","size":42},
    //   {"type":"com.stackoverflow.q8416904.Zab","name":"ZAB","hungry":true}
    // ]

    Foo foo = new Foo(bars);

    String json2 = mapper.writeValueAsString(foo);
    System.out.println(json2);
    // output:
    // {
    //   "bars":
    //   [
    //     "java.util.ArrayList",
    //     [
    //       {"type":"com.stackoverflow.q8416904.Baz","name":"BAZ","size":42},
    //       {"type":"com.stackoverflow.q8416904.Zab","name":"ZAB","hungry":true}
    //     ]
    //   ]
    // }

    mapper = new ObjectMapper().setVisibility(JsonMethod.FIELD, Visibility.ANY);
    mapper.enableDefaultTypingAsProperty(DefaultTyping.OBJECT_AND_NON_CONCRETE, "type");
    ObjectWriter typedWriter = mapper.writerWithType(mapper.getTypeFactory().constructCollectionType(List.class, Bar.class));

    String json3 = typedWriter.writeValueAsString(bars);
    System.out.println(json3);
    // output:
    // [
    //   "java.util.ArrayList",
    //   [
    //     {"type":"com.stackoverflow.q8416904.Baz","name":"BAZ","size":42},
    //     {"type":"com.stackoverflow.q8416904.Zab","name":"ZAB","hungry":true}
    //   ]
    // ]
  }
}

【讨论】:

  • 啊哦,我非常接近解决方案)当我第一次尝试时,有些东西给了我一个 NPE,我认为它不起作用。现在我再次尝试,一切正常。谢谢!
猜你喜欢
  • 2021-12-21
  • 2018-07-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-23
  • 1970-01-01
  • 2021-11-08
  • 2016-08-05
相关资源
最近更新 更多