Spring序列,Jackson Json在序列化和反序列化时出现问题

时间:2017-05-30 07:21:07

标签: java json spring-boot jackson objectmapper

对于某些用例,我需要将一个POJO转换为另一个具有不同字段名称的POJO。我尝试使用Jackson对象映射器。它在某种程度上有效。然而最终的结果并不是我的预期。

public class JacksonTest {

    public static void main(String[] args) throws IOException{
        ObjectMapper mapper = new ObjectMapper();
        User user = new User("Deepak", "111", "Singapore");
        UserMap newUser = mapper.convertValue(user, UserMap.class);
        System.out.println("SOUT: " + newUser);
        System.out.println("Jackson: " + mapper.writeValueAsString(newUser));
    }
}

class User {

    User(String name, String id, String address){
        this.name = name;
        this.id = id;
        this.address = address;
    }

    String name;
    String id;
    String address;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

class UserMap implements Serializable {
    @JsonProperty("name")
    String name;

    private Map<String, Object> meta = new HashMap<>();

    @JsonAnyGetter
    public Map<String, Object> any() {
        return meta;
    }

    @JsonAnySetter
    public void set(String name, Object value) {
        meta.put(name, value);
    }

    @Override
    public String toString() {
        return "UserMap{" +
                "name_new='" + name + '\'' +
                ", meta=" + meta.keySet().stream().map(x-> x+ ":: "+ meta.get(x)).collect(Collectors.joining(", ")) +
                '}';
    }
}

如果你跑,输出将是:

SOUT:UserMap {name_new =&#39; Deepak&#39;,meta = address :: Singapore,id :: 111}

杰克逊:{&#34;名称&#34;:&#34;迪帕克&#34;,&#34;地址&#34;:&#34;新加坡&#34;,&#34; id&#34; :&#34; 111&#34;}

我使用的是Springboot,它内部使用了jackson序列化程序。它会再次将 newUser 对象转换为普通用户类。我想以类构造的方式序列化字符串。我希望输出采用SOUT格式。

2 个答案:

答案 0 :(得分:0)

我认为你误解了@JsonAnyGetter/@JsonAnySetter对实际上会做什么。

它允许您创建一个几乎动态的 bean,包括强制字段和自愿字段。在您的情况下,名称将是强制性的,所有其他字段都是自愿的。

幕后发生的事情是,您的UserMap会转换为User。您看到的是序列化的UserMap,但由于它与相应的User实例具有相同的字段和值,因此它们的序列化表单看起来完全相同。

答案 1 :(得分:0)

我无法使用默认的Spring boot bean来进行自动序列化和反序列化。最后,在加入Project Lombok和apache BeanUtils之后,对我来说效果很好:

@ToString() @Getter() @Setter() @NoArgsConstructor()
public class User {
    private String email;
    private String bio;
    private String image;
    private String displayName;
    private String userId;
    private long lat;
    private long lng;

    public User(String json) throws JsonParseException, JsonMappingException, IOException, IllegalAccessException, InvocationTargetException {
        ObjectMapper om = new ObjectMapper();
        User u = om.readValue(json, User.class);
        BeanUtils.copyProperties(this, u);
    }
}

http://commons.apache.org/proper/commons-beanutils/download_beanutils.cgi https://projectlombok.org/