有没有可能有一个带有非默认构造函数的Jackson自定义反序列化程序?

gstyhher  于 2022-11-08  发布在  其他
关注(0)|答案(5)|浏览(122)

假设我有以下类:

public class Person {

    String name;
    Set<Department> departments;

}

public class Department {

    String code;
    String name;

}

所以我想写一个自定义的Department反序列化器,以便注解Person类中的departments字段来使用它。因为这个自定义的反序列化器只用于反序列化Person对象中的Department对象。问题是我的自定义Department反序列化器需要有一个DepartmentRepository,它必须在反序列化器的构造函数中传递。我该怎么做?这可能吗?我不知道。我不想在对象Map器中注册反序列化程序,因为只有当Person类的deparatments字段被反序列化时,才必须使用它。

**UPDATE:**我需要的是,除了使用参数contentUsing = MyCustomDepartmentDeserializer.class的JsonDeserialize注解来注解departments字段之外,还需要一种方法来告诉Jackson,当它建立MyCustomDepartmentDeserializer对象时,必须呼叫接收DepartmentRepository的建构函式来完成。这个反序列化程式可能如下所示:

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!
    }

}
ny6fqffe

ny6fqffe1#

首先要做的是:若要指定要用于数组内容的还原序列化程式,您可以使用

@JsonDeserialize(contentUsing=MyDeserializer.class)
Set<Department> departments;

以指定要用于相关集合内容的反序列化程序。
至于使用非默认构造函数的能力,@JsonCreator允许这样做。但是要传递一个上下文对象,你需要Jackson1.9可能是你的朋友(参见“Jackson 1.9 overview“),它允许“注入”JSON之外的对象。然后你可以混合和匹配可注入的值和JSON属性,例如:

public class POJO {
  @JsonCreator // can also be used for static factory methods
  public POJO(@JacksonInject DepartmentRepository repo, @JsonProperty("value") int value) {
      ....
  }
}

这可能足以满足您的要求。

btxsgosb

btxsgosb2#

您可以使用ObjectMapper将自订序列化程式/还原序列化程式注册为模块,以加入具有非预设建构函式的自订序列化程式/还原序列化程式。

SimpleModule simpleModule = new SimpleModule();
JsonDeserializer<MyObject> customDeserializer = new CustomDeserializer("Blah");
simpleModule.addDeserializer(MyObject.class, customDeserializer);
mapper.registerModule(simpleModule);

如果MyObject类中有注解,还应该将其删除。

erhoui1w

erhoui1w3#

这是我刚写的一个反序列化器。注意非默认构造函数的使用。

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);
}
}

请注意,在建立还原序列化程式并将它加入至模块时,您可以使用任何您喜欢的建构函式模式。

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);
xxb16uws

xxb16uws4#

不,在最开始的时候,你可以不指定一个自定义的反序列化器;Jackson可以检测嵌套字段并正确Map它们,* 只有当所有模型类都实现Serializable * 时。
所以,把implements Serializable加到DepartmentPerson上,你就会看到Jackson的作品开箱即用。

vfh0ocws

vfh0ocws5#

我相信您可以使用Jackson中的注解来标识要公开的属性。

相关问题