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

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

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"]]

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

// 测试类
import java.util.Iterator;
import java.util.ArrayList;
import java.util.List;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonTypeInfo;

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "class", visible=true)
public class IteratorTest<T> implements Iterator<T> {
    @JsonIgnore
    private Iterator<T> iterData;
    private static final ObjectMapper MAPPER = new ObjectMapper();
    IteratorTest(Iterator<T> iterData) { this.iterData = iterData; }
    
    @Override 
    public boolean hasNext() {
        return iterData.hasNext();
    }
    @Override
    public T next() {
        return iterData.next();
    }

    public static void main(String[] args) throws IOException {
        List<String> strings = new ArrayList<>();
        strings.add("one");
        strings.add("two");

        IteratorTest<String> it = new IteratorTest<>(strings.iterator());

        System.out.println("-- serializing --");
        String s = MAPPER.writeValueAsString(it);
        System.out.println(s);
    }
}
// 测试类结尾
英文:

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?

// Test class
import java.util.Iterator;
import java.util.ArrayList;
import java.util.List;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonTypeInfo;

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = &quot;@class&quot;, visible=true)
public class IteratorTest&lt;T&gt; implements Iterator&lt;T&gt; {
	@JsonIgnore	
	private Iterator&lt;T&gt; iterData;
    private static final ObjectMapper MAPPER = new ObjectMapper();
	IteratorTest(Iterator&lt;T&gt; iterData) { this.iterData = iterData; }
	
	@Override 
	public boolean hasNext() {
		return iterData.hasNext();
	}
	@Override
	public T next() {
		return iterData.next();
	}

	public static void main(String[] args) throws IOException {
		List&lt;String&gt; strings = new ArrayList&lt;&gt;();
		strings.add(&quot;one&quot;);
		strings.add(&quot;two&quot;);

		IteratorTest&lt;String&gt; it = new IteratorTest&lt;&gt;(strings.iterator());

		System.out.println(&quot;-- serializing --&quot;);
		String s = MAPPER.writeValueAsString(it);
		System.out.println(s);
    }
}
// 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):
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "myClass")
class IteratorTest<T> implements Iterator<T> {

    private String myClass = IteratorTest.class.getSimpleName();

    ...
}
英文:

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):

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

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:

确定