英文:
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 = "@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);
}
}
// 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 = "myClass") class IteratorTest<T> implements Iterator<T> { private String myClass = IteratorTest.class.getSimpleName(); ... }
专注分享java语言的经验与见解,让所有开发者获益!
评论