杰克逊序列化子类

3
在下面的例子中,我有一个主类A和它的子类B。这两个类都可以作为通用类X中的属性。
public class A
{
   @JsonProperty("primary_key")
   public final String primaryKey;

   @JsonCreator
   A(@JsonProperty("primary_key") String primaryKey)
   {
        this.primaryKey = primaryKey;
   }
}
public class B extends A
{
   @JsonProperty("secondary_key")
   public final String secondaryKey;

   @JsonCreator
   B(@JsonProperty("primary_key") String primaryKey, @JsonProperty("secondary_key") String secondaryKey)
   {
        super(primaryKey);
        this.secondaryKey = secondaryKey;
   }
}

public class X
{
    @JsonProperty("keys")
    public final A keys;

    @JsonCreator
    X(@JsonProperty("keys") A keys)
    {
         this.keys = keys;
    }
}

我可以帮您进行翻译。以下是关于如何使用Jackson多态特性,正确地将下面给定的Json反序列化为它们各自的类的内容:
Json A:
 { "keys" :{
              "primary_key" : "abc"
          }
 }

JSON B :

 { "keys" : {
              "primary_key" : "abc",
              "secondary_key" : "xyz"
         }
    }

期望结果:将地图键对象映射到 JSON A 的 A 类和 JSON B 的 B 类。 请提出替代建议。

你的实际结果和期望结果不太清楚。 - undefined
@YusufK. 我想将第一个 JSON 映射到 A 类,将第二个 JSON 映射到 B 类。 - undefined
我觉得你想要从每个给定的 JSON 中创建对象? - undefined
是的,@YusufK。我想根据给定的 JSON 创建对象。 - undefined
2个回答

1

这似乎是一个相当普遍的问题,没有简单的注释方式可以解决它(或者说我只是找不到一种):

Jackson多态反序列化-您能要求存在字段而不是特定值吗?

使用Jackson反序列化多态类型

你可以做的一件事是向你的对象映射器添加自定义反序列化器。这里有一个很好的演示:https://stackoverflow.com/a/19464580/1032167

这里是与您的示例相关的演示:

import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.module.SimpleModule;

import java.io.IOException;

public class Main4 {


private static final String jsonA = "{ \"keys\" : { \"primary_key\" : \"abc\" } }";
private static final String jsonB = 
        "{ \"keys\" : { \"primary_key\" : \"abc\", \"secondary_key\" : \"xyz\" } }";

public static void main(String[] args) throws IOException {
    ObjectMapper mapper = new ObjectMapper();

    SimpleModule idAsRefModule = new SimpleModule("ID-to-ref");
    idAsRefModule.addDeserializer(A.class, new AJsonDeserializer());
    mapper.registerModule(idAsRefModule);

    X tl = mapper.readValue(jsonA, X.class);
    System.out.println(tl);

    X t2 = mapper.readValue(jsonB, X.class);
    System.out.println(t2);
}

public static class AJsonDeserializer  extends JsonDeserializer<A>{

    @Override
    public A deserialize(JsonParser jp, DeserializationContext dc)
    throws IOException {

        ObjectCodec codec = jp.getCodec();
        JsonNode node = codec.readTree(jp);

        if (node.has("secondary_key")) {
            return codec.treeToValue(node, B.class);
        }
        return new A(node.findValue("primary_key").asText());
    }
}

public static class A
{
    @JsonProperty("primary_key")
    public final String primaryKey;

    @JsonCreator
    A(@JsonProperty("primary_key") String primaryKey)
    {
        this.primaryKey = primaryKey;
    }

    @Override
    public String toString() {
        return "A{" +
                "primaryKey='" + primaryKey + '\'' +
                '}';
    }
}

public static class B extends A
{
    @JsonProperty("secondary_key")
    public final String secondaryKey;

    @JsonCreator
    B(@JsonProperty("primary_key") String primaryKey, 
      @JsonProperty("secondary_key") String secondaryKey)
    {
        super(primaryKey);
        this.secondaryKey = secondaryKey;
    }

    @Override
    public String toString() {
        return "B{" +
                "primaryKey='" + primaryKey + '\'' +
                "secondaryKey='" + secondaryKey + '\'' +
                '}';
    }
}

public static class X
{
    @JsonProperty("keys")
    public final A keys;

    @JsonCreator
    X(@JsonProperty("keys") A keys)
    {
        this.keys = keys;
    }

    @Override
    public String toString() {
        return "X{" +
                "keys=" + keys +
                '}';
    }
}
}

但是,如果您想使用默认的A反序列化程序,您将需要创建另一个超级类,或者请参阅此处以了解如何解决此问题:https://dev59.com/iGMl5IYBdhLWcg3wingW#18405958


0

如果我理解正确的话,只需传递这些值就可以了,不需要任何配置。我相信这就是你所寻找的:

public class Test {

    private static final String JSON = "{\"keys\":{\"primary_key\":\"abc\",\"secondary_key\":\"xyz\"}}";

    public static void main(String[] args) throws IOException {

        ObjectMapper mapper = new ObjectMapper();
        X x = mapper.readValue(JSON, X.class);
        System.out.println(mapper.writeValueAsString(x));

    }
}

class A {
    private String primary_key;

    public String getPrimary_key() {
        return primary_key;
    }

    public void setPrimary_key(String primary_key) {
        this.primary_key = primary_key;
    }
}

class B extends A {

    private String secondary_key;

    public String getSecondary_key() {
        return secondary_key;
    }

    public void setSecondary_key(String secondary_key) {
        this.secondary_key = secondary_key;
    }
}

class X {

    private B keys;

    public B getKeys() {
        return keys;
    }

    public void setKeys(B keys) {
        this.keys = keys;
    }
}

输出将是:

{"keys":{"primary_key":"abc","secondary_key":"xyz"}}

如果这不是您期望的内容,请提供另一个解释,我会根据需要编辑答案。


1
如果给定的 JSON 包含 "secondary_key",那么 X 中的键对象应属于 B;否则,X 中的键对象应属于 A。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接