在反序列化JSON时为类创建指定其他参数。

时间:2023-01-12 18:05:28

Jackson has the handy feature that you can specify custom constructors or static factory methods to use when creating a class, getting parameters from the JSON object. However, I'm not sure what the best way is to pass an additional constructor argument to a deserialized object. For example, I'd like to be able to have Jackson use this JSON to construct and initialize the following class:

Jackson具有便利的特性,您可以指定自定义构造函数或静态工厂方法,以便在创建类时使用它们,从JSON对象获取参数。但是,我不确定向反序列化对象传递附加构造函数参数的最佳方式是什么。例如,我想让Jackson使用这个JSON构造并初始化以下类:

{
    "x": "foo",
    "y": "bar",
    "z": "baz"
}

public class Foo {
    /*
     * conf and x <b>must</b> be supplied at construction time
     */
    @JsonCreator
    public Foo(Configuration conf, @JsonValue("x") String x)

    public String getX();

    public String getY();
    public void setY(String y);
    public String getZ();
    public void setZ(String z);
}

public class SomeMainApplicationClass {
    public Foo loadFoo(InputStream in, Configuration conf) {
        ObjectMapper mapper = new ObjectMapper(/* ??? */);
        /* ??? */
        return mapper.readValue(in, Foo.class);
    }
}

My first instinct was that I needed to create some sort of factory object:

我的第一反应是,我需要创建某种工厂对象:

public class FooFactory {
    private final Configuration conf;
    public FooFactory(Configuration conf) {
        this.conf = conf;
    }
    @JsonCreator
    public createFoo(@JsonProperty("x") String x) {
        return new Foo(conf, x);
    }
}

But Jackson doesn't have a straightforward way to plug that in--most of the methods I've found (or annotation-based options) use static factory methods.

但是Jackson并没有一种简单的方法来插入——我找到的大多数方法(或者基于注释的选项)都使用静态的工厂方法。

The answer must not use global/static variables--I want to configure the Configuration object on a per-ObjectMapper basis.

答案必须不使用全局/静态变量——我希望在每个objectmapper的基础上配置配置配置对象。

My preferred answer should:

我喜欢回答应该:

  • Be brief! I know there are multiple ways to approach this, I'm looking for the simplest one
  • 是短暂的!我知道有很多方法可以达到这个目的,我在寻找最简单的方法
  • Continue to leverage Jackson's ability to use reflection and interpret data-binding annotations for the non-constructor properties, rather than writing a Deserializer that has to be updated every time I add or edit a settable property
    • Should not require me to manually read and buffer the object properties from JSON (i.e. don't duplicate BeanDeserializer._deserializeUsingPropertyBased)
    • 不应该要求我从JSON中手动读取和缓冲对象属性(例如,不要复制BeanDeserializer._deserializeUsingPropertyBased)
  • 继续利用杰克逊使用反射的能力和解释数据绑定non-constructor属性的注释,而不是写一串并转换器必须更新每次添加或编辑一个可设置的属性应该不需要我手动阅读和缓冲区从JSON对象属性(即不要重复BeanDeserializer._deserializeUsingPropertyBased)
  • Work with annotation mix-ins
  • 使用注释mix - in

I've explored setting up custom CreatorContainers or DeserializerProviders, but I haven't come up with a method that meets my requirements yet.

我已经研究过如何设置定制的creatorcontainer或deserializerprovider,但是我还没有找到一个满足我的需求的方法。

1 个解决方案

#1


1  

There is no current facility to do this; would "ability to inject values during deserialization" (see http://jira.codehaus.org/browse/JACKSON-406) do this? You might want to ask this on Jackson user (or dev) mailing list, as this is one of higher priority features that hopefully will be worked on for Jackson 1.9.

目前还没有这样的设施;“在反序列化期间注入值的能力”(参见http://jira.codehaus.org/browse/JACKSON-406)会这样做吗?您可能想问这个关于Jackson用户(或dev)邮件列表的问题,因为这是希望为Jackson 1.9提供的更高优先级特性之一。

One possibility is to just use @JsonCreator, decorate all parameters with @JsonParameter, and access value from there -- if there is no matching property, you will get null as value. This is not optimal, but if you can access value you need (via ThreadLocal, filled prior to calling deserialization) you would at least be able to solve this.

一种可能是使用@JsonCreator,使用@JsonParameter修饰所有参数,并从那里访问值——如果没有匹配属性,您将获得null作为值。这不是最优的,但是如果您能够访问您需要的值(通过ThreadLocal,在调用反序列化之前填充),您至少能够解决这个问题。

#1


1  

There is no current facility to do this; would "ability to inject values during deserialization" (see http://jira.codehaus.org/browse/JACKSON-406) do this? You might want to ask this on Jackson user (or dev) mailing list, as this is one of higher priority features that hopefully will be worked on for Jackson 1.9.

目前还没有这样的设施;“在反序列化期间注入值的能力”(参见http://jira.codehaus.org/browse/JACKSON-406)会这样做吗?您可能想问这个关于Jackson用户(或dev)邮件列表的问题,因为这是希望为Jackson 1.9提供的更高优先级特性之一。

One possibility is to just use @JsonCreator, decorate all parameters with @JsonParameter, and access value from there -- if there is no matching property, you will get null as value. This is not optimal, but if you can access value you need (via ThreadLocal, filled prior to calling deserialization) you would at least be able to solve this.

一种可能是使用@JsonCreator,使用@JsonParameter修饰所有参数,并从那里访问值——如果没有匹配属性,您将获得null作为值。这不是最优的,但是如果您能够访问您需要的值(通过ThreadLocal,在调用反序列化之前填充),您至少能够解决这个问题。