java 是否可以使用非默认构造函数的 Jackson 自定义反序列化器?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7781203/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is it possible to have a Hymanson custom deserializer with non-default constructor?
提问by GuidoMB
Lets say that I have the following classes:
假设我有以下课程:
public class Person {
String name;
Set<Department> departments;
}
public class Department {
String code;
String name;
}
So I want to write a custom Department deserializer in order to annotate the deparments field in the Person class to use it. Because this custom deserializer will only be used to deserialize Department objects that are inside a Person object. The problem is that my custom Department deserializer will need to have a DepartmentRepository that must be passed in the deserializer's constructor. How can I do this? Is this possible? I don't want to register the deserializer in the object mapper because it must only be used when the deparatments field from the Person class gets deserialized.
所以我想编写一个自定义的Department 反序列化器,以便注释Person 类中的deparments 字段以使用它。因为此自定义反序列化器仅用于反序列化 Person 对象内的 Department 对象。问题是我的自定义 Department 反序列化器需要有一个 DepartmentRepository,它必须在反序列化器的构造函数中传递。我怎样才能做到这一点?这可能吗?我不想在对象映射器中注册反序列化器,因为它只能在 Person 类中的 deparatments 字段被反序列化时使用。
UPDATE:What I need is, apart from annotate the departments field with JsonDeserialize annotation with the parameter contentUsing = MyCustomDepartmentDeserializer.class, is a way to tell Hymanson that when it creates a MyCustomDepartmentDeserializer object, it must done it by calling a constructor that receives a DepartmentRepository. The deserializer may be something like this:
更新:我需要的是,除了使用参数 contentUsing = MyCustomDepartmentDeserializer.class 用 JsonDeserialize 注释对部门字段进行注释之外,还有一种方法告诉Hyman逊,当它创建一个 MyCustomDepartmentDeserializer 对象时,它必须通过调用接收部门资料库。解串器可能是这样的:
public class MyCustomDepartmentDeserializer extends JsonDeserializer<Department> {
private final DepartmentRepository departmentRepository;
public MyCustomDepartmentDeserializer(DepartmentRepository departmentRepository) {
this.departmentRepository = departmentRepository;
}
@Override
public Department deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
//IMPLEMENTATION!
}
}
回答by herrtim
You can add a custom serializer/deserializer with a non-default constructor by registering it as a module with you ObjectMapper
.
您可以通过将其注册为模块来添加具有非默认构造函数的自定义序列化器/反序列化器ObjectMapper
。
SimpleModule simpleModule = new SimpleModule();
JsonDeserializer<MyObject> customDeserializer = new CustomDeserializer("Blah");
testModule.addDeserializer(MyObject.class, customDeserializer);
mapper.registerModule(simpleModule);
You should also remove the annotation in the MyObject
class if it's there.
您还应该删除MyObject
类中的注释(如果存在)。
回答by StaxMan
First things first: to specify deserializer to use for contents of an array you can use
第一件事:指定反序列化器以用于您可以使用的数组内容
@JsonDeserialize(contentUsing=MyDeserializer.class)
Set<Department> departments;
to specify deserializer to use for contents of the collection in question.
指定用于相关集合内容的反序列化器。
As to ability to use non-default constructors, @JsonCreator allows this. But to pass a context object, you need Hymanson 1.9 may be your friend (see "Hymanson 1.9 overview"), which allows "injection" of objects outside of JSON. You can then mix and match injectable values and JSON properties, for example:
至于使用非默认构造函数的能力,@JsonCreator 允许这样做。但是要传递上下文对象,您需要 Hymanson 1.9 可能是您的朋友(请参阅“ Hymanson 1.9 概述”),它允许“注入”JSON 之外的对象。然后,您可以混合和匹配可注入值和 JSON 属性,例如:
public class POJO {
@JsonCreator // can also be used for static factory methods
public POJO(@HymansonInject DepartmentRepository repo, @JsonProperty("value") int value) {
....
}
}
This might be enough to do what you are asking.
这可能足以满足您的要求。
回答by bmargulies
Here is a deserializer I just wrote. Note the use of a non-default constructor.
这是我刚刚写的一个解串器。请注意非默认构造函数的使用。
public class SparseStringArrayVectorDeserializer extends JsonDeserializer<SparseStringArrayVector> {
@Override
public SparseStringArrayVector deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
/* This isn't the most efficient way to do this, since we're building a tree of nodes that we will discard.
* However, we need to change the order around, so something like this is hard to avoid.
*/
JsonNode tree = jp.readValueAsTree();
int tokenCount = tree.size();
int[] indexes = new int[tokenCount];
String[][] strings = new String[tokenCount][];
Iterator<Entry<String, JsonNode>> fieldNameIt = tree.getFields();
int slot = 0;
while (fieldNameIt.hasNext()) {
Entry<String, JsonNode> entry = fieldNameIt.next();
int index = Integer.parseInt(entry.getKey());
indexes[slot] = index;
String[] thisTokenStrings = new String[entry.getValue().size()];
for (int x = 0; x < thisTokenStrings.length; x++) {
thisTokenStrings[x] = entry.getValue().get(x).getTextValue();
}
strings[slot] = thisTokenStrings;
slot++;
}
return new SparseStringArrayVector(indexes, strings);
}
}
Used with the following. Note that you could have any constructor pattern that you like when creating the deserializer and adding it to the module.
与以下一起使用。请注意,在创建反序列化器并将其添加到模块时,您可以使用任何您喜欢的构造函数模式。
ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule("ResultAccess", new Version(7, 4, 0, null));
module.addDeserializer(SparseStringArrayVector.class, new SparseStringArrayVectorDeserializer());
module.addDeserializer(AbstractResultAccess.class, new ProxyAbstractResultAccessDeserializer());
mapper.registerModule(module);
回答by WesternGun
No, at the very beginning, you can go without specify a custom deserializer; Hymanson can detect your nested field and map them correctly, only when all the model classes implements Serializable
.
不,一开始,您可以不指定自定义解串器;Hymanson 可以检测您的嵌套字段并正确映射它们,只有当所有模型类都实现Serializable
.
So, add implements Serializable
to Department
and Person
, and you will see Hymanson works out of the box.
所以,添加implements Serializable
到Department
和Person
,你会看到Hyman逊开箱即用。
回答by Chris J
Just off the top of my head, I am pretty sure you can do that using the annotations in Hymanson to identify which properties you want to exposure.
就在我的脑海中,我很确定您可以使用 Hymanson 中的注释来确定要公开的属性。