Jackson序列化是否会忽略Iterator类的@JsonTypeInfo和@JsonIgnore?

huangapple 未分类评论63阅读模式
英文:

Jackson serialization ignores '@JsonTypeInfo' and '@JsonIgnore' for Iterator classes?

问题

我最近从Jackson 2.9.10升级到2.10.0,并注意到迭代器类的序列化方式发生了变化。

在下面的测试中,使用2.9.10版本(处理JsonTypeInfo和JsonIgnore)的输出为:

{"@class":"IteratorTest"}

但是在2.10.0版本中,JsontTypeInfo和JsonIgnore未被处理,输出为:

["IteratorTest",["one","two"]]

新的序列化行为是否正确?是否有方法来获得旧的行为?

  1. // 测试类
  2. import java.util.Iterator;
  3. import java.util.ArrayList;
  4. import java.util.List;
  5. import com.fasterxml.jackson.databind.ObjectMapper;
  6. import java.io.IOException;
  7. import com.fasterxml.jackson.annotation.JsonIgnore;
  8. import com.fasterxml.jackson.annotation.JsonTypeInfo;
  9. @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "class", visible=true)
  10. public class IteratorTest<T> implements Iterator<T> {
  11. @JsonIgnore
  12. private Iterator<T> iterData;
  13. private static final ObjectMapper MAPPER = new ObjectMapper();
  14. IteratorTest(Iterator<T> iterData) { this.iterData = iterData; }
  15. @Override
  16. public boolean hasNext() {
  17. return iterData.hasNext();
  18. }
  19. @Override
  20. public T next() {
  21. return iterData.next();
  22. }
  23. public static void main(String[] args) throws IOException {
  24. List<String> strings = new ArrayList<>();
  25. strings.add("one");
  26. strings.add("two");
  27. IteratorTest<String> it = new IteratorTest<>(strings.iterator());
  28. System.out.println("-- serializing --");
  29. String s = MAPPER.writeValueAsString(it);
  30. System.out.println(s);
  31. }
  32. }
  33. // 测试类结尾
英文:

I've recently upgraded from Jackson 2.9.10 to 2.10.0 and notice a change in how Iterator classes are serialized.

Given the test below, the output with 2.9.10 (with handling of JsonTypeInfo and JsonIgnore) is

{"@class":"IteratorTest"}

but with 2.10.0, JsontTypeInfo and JsonIgnore are not processed, and the output is

["IteratorTest",["one","two"]]

Is the new serialization behavior correct? Is there a workaround to get the old behavior?

  1. // Test class
  2. import java.util.Iterator;
  3. import java.util.ArrayList;
  4. import java.util.List;
  5. import com.fasterxml.jackson.databind.ObjectMapper;
  6. import java.io.IOException;
  7. import com.fasterxml.jackson.annotation.JsonIgnore;
  8. import com.fasterxml.jackson.annotation.JsonTypeInfo;
  9. @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = &quot;@class&quot;, visible=true)
  10. public class IteratorTest&lt;T&gt; implements Iterator&lt;T&gt; {
  11. @JsonIgnore
  12. private Iterator&lt;T&gt; iterData;
  13. private static final ObjectMapper MAPPER = new ObjectMapper();
  14. IteratorTest(Iterator&lt;T&gt; iterData) { this.iterData = iterData; }
  15. @Override
  16. public boolean hasNext() {
  17. return iterData.hasNext();
  18. }
  19. @Override
  20. public T next() {
  21. return iterData.next();
  22. }
  23. public static void main(String[] args) throws IOException {
  24. List&lt;String&gt; strings = new ArrayList&lt;&gt;();
  25. strings.add(&quot;one&quot;);
  26. strings.add(&quot;two&quot;);
  27. IteratorTest&lt;String&gt; it = new IteratorTest&lt;&gt;(strings.iterator());
  28. System.out.println(&quot;-- serializing --&quot;);
  29. String s = MAPPER.writeValueAsString(it);
  30. System.out.println(s);
  31. }
  32. }
  33. // end of Test class

答案1

得分: 0

是的,在版本2.9.10中,您会得到一个BeanSerializer,而在版本2.10.0中,您会得到一个IteratorSerializer

在版本2.10.0中,当您的类没有任何属性时(BeanSerializerFactory.findSerializerByAddonType),您会得到IteratorSerializer。而在版本2.9.10中,您可以从builder.createDummy()获得一个BeanSerializer

修复方法:

  • 使用自定义序列化程序
  • 或许更改您的OM的Iterator类处理方式
  • 使用现有的属性,以便创建BeanSerializer(这将给您不同的JSON):
  1. @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "myClass")
  2. class IteratorTest<T> implements Iterator<T> {
  3. private String myClass = IteratorTest.class.getSimpleName();
  4. ...
  5. }
英文:

Yes, debugging it, with version 2.9.10 you get a BeanSerializer, with version 2.10.0 you get a IteratorSerializer.

In version 2.10.0, you get the IteratorSerializer when your class does not have any properties (BeanSerializerFactory.findSerializerByAddonType). In version 2.9.10, you get a BeanSerializer from builder.createDummy().

Fix:

  • Use a custom serializer

  • maybe change the handling of Iterator-Classes for your OM

  • Use an existing property, s.t. a BeanSerializer is created (this would give you a different json):

    1. @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = &quot;myClass&quot;)
    2. class IteratorTest&lt;T&gt; implements Iterator&lt;T&gt; {
    3. private String myClass = IteratorTest.class.getSimpleName();
    4. ...
    5. }

huangapple
  • 本文由 发表于 2020年3月16日 07:29:51
  • 转载请务必保留本文链接:https://java.coder-hub.com/60698714.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定