是否可以使用Jackson2中的Mixin对派生值反序列化多版本JSON

时间:2015-12-02 10:46:08

标签: jackson

我需要将JSON(有两个版本)转换为对象

第一版:

{"first_name":"John","last_name":"Doe"}

第二版:

{"fName":"John","lName":"Doe"}

我需要将JSON转换为

class User {
    private String fullName;

    public String getFullName() {
        return fullName;
    }
}

我遇到的一种方法是Mixin:

@Test
public void testMixinWorks_whenDeserialize() throws IOException {
    ObjectMapper mapperForV1 = new ObjectMapper();
    mapperForV1.addMixInAnnotations(User.class, UserV1Mixin.class);

    User userFromV1 = mapperForV1.readValue(
            "{\"first_name\":\"John\",\"last_name\":\"Doe\"}", User.class);

    assertThat(userFromV1.getFullName(), is("John Doe"));

    ObjectMapper mapperForV2 = new ObjectMapper();
    mapperForV2.addMixInAnnotations(User.class, UserV2Mixin.class);
    User userFromV2 = mapperForV2.readValue(
            "{\"fn\":\"John\",\"ln\":\"Doe\"}", User.class);

    assertThat(userFromV2.getFullName(), is("John Doe"));
}

static abstract class UserV1Mixin {
    @JsonCreator
    public UserV1Mixin(@JsonProperty("first_name") String firstName,
                       @JsonProperty("last_name") String lastName) {
    }
}

static abstract class UserV2Mixin {
    @JsonCreator
    public UserV2Mixin(@JsonProperty("fName") String firstName,
                       @JsonProperty("lName") String lastName) {
    }
}

但它不起作用,因为我不知道如何连接firstName和lastName。

是否可以使用Mixin反序列化派生值?

2 个答案:

答案 0 :(得分:1)

您可以使用基于代理的创建者。您的属性将以Map<String, Object>格式作为构造函数的参数。

public class User {

    private String fullName;

    @JsonCreator
    public User(Map<String, Object> props) {
        String firstName = "";
        String lastName = "";
        if (props.get("fName") != null) {
            firstName = (String) props.get("fName");
            lastName = (String) props.get("lName");
        }
        if (props.get("first_name") != null) {
            firstName = (String) props.get("first_name");
            lastName = (String) props.get("last_name");
        }
        this.fullName = firstName + " " + lastName;
    }

    public String getFullName() {
        return fullName;
    }

}

这将接受两个输入。 @JsonCreator还有其他用法。您可以在此博文中阅读它们:http://www.cowtowncoder.com/blog/archives/2011/07/entry_457.html

更新: 您可以为User.class

使用自定义反序列化程序
public class UserDeserializer extends JsonDeserializer<User> {

    @Override
    public User deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        JsonNode node = jp.getCodec().readTree(jp);
        User user = new User();
        if (node.has("fName")) {
            user.setFullName(node.get("fName").asText() + " " + node.get("lName").asText());
        } else if (node.has("first_name")) {
            user.setFullName(node.get("first_name").asText() + " " + node.get("last_name").asText());
        } else {
            throw new UnsupportedOperationException();
        }
        return user;
    }

}

    ObjectMapper om = new ObjectMapper();
    SimpleModule module = new SimpleModule();
    module.addDeserializer(User.class, new UserDeserializer());
    om.registerModule(module);
    User user = om.readValue(input, User.class);

答案 1 :(得分:1)

经过一番研究,我得到了一种使用Builder模式和Mixin的方法:

 /**
   * no annotation on this class therefore
   * this class is JSON version agnositc
   */
 class User {  
    private String fullName;

    public User(String fullName) {
        this.fullName = fullName;
    }

    public String getFullName() {
        return fullName;
    }
}


 /////////////////// v1 //////////////////////
@JsonPOJOBuilder(buildMethodName = "build", withPrefix = "set")
static class UserV1MixinBuilder {
    private String firstName;
    private String lastName;

    @JsonProperty("first_name")
    public UserV1MixinBuilder setFirstName(String value) {
        this.firstName = value;
        return this;
    }

    @JsonProperty("last_name")
    public UserV1MixinBuilder setLastName(String value) {
        this.lastName = value;
        return this;
    }

    public User build() {
        return new User(firstName + " " + lastName);
    }
}

@JsonDeserialize(builder = UserV1MixinBuilder.class)
static abstract class UserV1Mixin {

}

/////////////////// v2 //////////////////////
@JsonPOJOBuilder(buildMethodName = "build", withPrefix = "set")
static class UserV2MixinBuilder {
    private String firstName;
    private String lastName;

    @JsonProperty("fn")
    public UserV2MixinBuilder setFirstName(String value) {
        this.firstName = value;
        return this;
    }

    @JsonProperty("ln")
    public UserV2MixinBuilder setLastName(String value) {
        this.lastName = value;
        return this;
    }

    public User build() {
        return new User(firstName + " " + lastName);
    }
}

@JsonDeserialize(builder = UserV2MixinBuilder.class)
static abstract class UserV2Mixin {

}