如何将多个 json 字段反序列化为一个自定义对象 直接回答整体输出参考资料

问题描述

我正在尝试反序列化这样的 json:

{
  //other fields

  "name": "John","surname": "Doe"
}

变成这样的对象:

public class SomeClass {

  //other fields

  private User user;

  public class User {

      private String name;
      private String surname;
        
      //getters and setters
  }


//getters and setters
}

我尝试使用在静态方法上注释的@JsonCreator,但它不起作用(我对@JsonCreator 不太实用)。 有没有办法实现这一点,也许使用杰克逊注释?如何填充用户字段并正确填充“SomeClass”对象的“用户”字段?

注意:我不会改变json的结构或类。

更新:我找到了解决方案,但这不是一个好的解决方案 imo:

@JsonAnySetter
public void setFields(String key,String value) {

    if (user == null)
        user = new User();

    if (key.equals("name"))
        user.setName(value);
    else if (key.equals("surname"))
        user.setSurname(value);

}

有更好的方法吗?

解决方法

您可以为此使用 Jackson。我已经将 Jackson 2.12.1 和 Project Lombok 用于 getter 和 setter。下面是JSON序列化和反序列化的完整代码。

您的 JSON 结构需要更改为以下内容:

{
  "user":{
     "name": "John","surname": "Doe" 
  }
}

User.java 类:

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class User {
    private String name;
    private String surname;
}

SomeClass.Java 类:

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class SomeClass {
    private User user;
}

Main.java 类:

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class Main {

    public static void main(String[] args) throws JsonMappingException,JsonProcessingException {
        String inputJSON = "{\"user\":{\"name\":\"John\",\"surname\":\"Doe\"}}";
        SomeClass myUserRead = new ObjectMapper().readValue(inputJSON,SomeClass.class);
        System.out.println(myUserRead.getUser().getName());
        System.out.println(myUserRead.getUser().getSurname());

        String myUserWrite = new ObjectMapper().writeValueAsString(myUserRead);
        System.out.println(myUserWrite);
    }
,

可能的选项:Jackson 的 ObjectMapper,使用类或类型引用

直接回答

ObjectMapper mapper = new ObjectMapper(); // To do the work of serialization/deserialization
String json = "{"
      + "\"name\": \"John\",\n"
      + "\"surname\": \"Doe\"\n"
      + "}";

try {
    User user = mapper.readValue(json,User.class); // Deserializing directly to a Class is this easy :)

    String msg = String.format("With Class,User's Name: %s,User's Surname: %s",user.getName(),user.getSurname());
    System.out.println(msg);
} catch (JsonProcessingException e) {
    e.printStackTrace();
}

整体

(使用 IntelliJ 轻松访问测试库)

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.testng.annotations.Test;

public class TestDeserialization {

    private ObjectMapper mapper = new ObjectMapper(); // To do the work of serialization/deserialization
    private String json = "{"
                          + "\"name\": \"John\",\n"
                          + "\"surname\": \"Doe\"\n"
                          + "}"; // Not a good way to store JSON,but here for demonstration :)

    @Test
    public void testDeserializationWithClass() {
        try {
            User user = mapper.readValue(json,User.class); // Deserializing directly to a Class is this easy :)

            String msg = String.format("With Class,user.getSurname());
            System.out.println(msg);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }


    @Test
    public void testDeserializationWithTypeReference() {
        try {
            /*
                TypeReference can handle complexity where the simple Class argument cannot; such as if we needed a Map<String,User>:
                    Map<String,User> userMap = mapper.readValue(json,new TypeReference<Map<String,User>>() {}); 
            */
            User user = mapper.readValue(json,new TypeReference<User>() {}); 

            String msg = String.format("With TypeReference,user.getSurname());
            System.out.println(msg);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }

}
package test.example;

public class User {

    private String name;
    private String surname;

    public String getName() {
        return name;
    }

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

    public String getSurname() {
        return surname;
    }

    public void setSurname(String surname) {
        this.surname = surname;
    }
}

输出

With Class,User's Name: John,User's Surname: Doe
With TypeReference,User's Surname: Doe

参考资料