[英]How to convert JSON to Java object if I do not know all json fields before parsing?
我的服務可以接收幾個不同的 json,例如:
{
"event":"conversation_started",
"context":"context information",
"user":{
"id":"01234567890A=",
"name":"John McClane",
"avatar":"http://avatar.example.com",
"country":"UK",
"language":"en",
"api_version":1
},
"subscribed":false
}
或者
{
"event":"message",
"message":{
"type":"text",
"text":"a message to the service",
"location":{
"lat":12.34,
"lon":12.34
}
}
}
或其他幾個json。 所有 json 唯一相同的字段是“事件”。 所有其他字段可以不同(取決於“事件”值)。
所以問題是:如何將這些 json 轉換為 java 對象(不編寫混亂的代碼)? 我知道的唯一方法是手動檢查“事件”值(如json.startsWith("{\n\"event\":\"message\"")
但我確信這樣做有任何簡單的決定.
UPD:如果您不想通過聲明 POJO 將 JSON 字符串轉換為 JAVA Object,則可以將其解析為JSONObject
.
public class Event {
public static void main(String[] args) {
String jsonA = "{\"event\":\"conversation_started\",\"context\":\"context information\",\"user\":{\"id\":\"01234567890A=\",\"name\":\"John McClane\",\"avatar\":\"http://avatar.example.com\",\"country\":\"UK\",\"language\":\"en\",\"api_version\":1},\"subscribed\":false}";
String jsonB = "{\"event\":\"message\",\"message\":{\"type\":\"text\",\"text\":\"a message to the service\",\"location\":{\"lat\":12.34,\"lon\":12.34}}}";
JSONObject jsonObject = JSONObject.parseObject(jsonA);
String event = jsonObject.getString("event");
if (event.equals("message")) {
//do what you want to do
System.out.println("message event......");
} else if ("conversation_started".equals(event)) {
System.out.println("context information event......");
}
}
}
如下聲明一個Event
的class,然后將JSON字符串轉換為一個Event
JAVA ZA8CFDE63311BD59EB26ACZF86。
@Data
public class Event {
private String event;
private String context;
private User user;
private boolean subscribed;
private Message message;
@Data
public static class User {
private String id;
private String name;
private String avatar;
private String country;
private String language;
private int api_version;
}
@Data
public static class Message {
private String type;
private String text;
private Location location;
@Data
public static class Location {
private double lat;
private double lon;
}
}
public static void main(String[] args) {
String jsonA = "{\"event\":\"conversation_started\",\"context\":\"context information\",\"user\":{\"id\":\"01234567890A=\",\"name\":\"John McClane\",\"avatar\":\"http://avatar.example.com\",\"country\":\"UK\",\"language\":\"en\",\"api_version\":1},\"subscribed\":false}";
String jsonB = "{\"event\":\"message\",\"message\":{\"type\":\"text\",\"text\":\"a message to the service\",\"location\":{\"lat\":12.34,\"lon\":12.34}}}";
ObjectMapper objectMapper = new ObjectMapper();
try {
Event eventA = objectMapper.readValue(jsonA, new TypeReference<Event>() {
});
System.out.println(objectMapper.writeValueAsString(eventA));
Event eventB = objectMapper.readValue(jsonB, new TypeReference<Event>() {
});
System.out.println(objectMapper.writeValueAsString(eventB));
} catch (IOException e) {
e.printStackTrace();
}
}
}
使用 JSON object。 這是動態的,可以加載任何 json。 然后您可以一致地引用事件字段
示例 1
//import java.util.ArrayList;
//import org.bson.Document;
Document root = Document.parse("{ \"event\" : \"conversation_started\", \"context\" : \"context information\", \"user\" : { \"id\" : \"01234567890A=\", \"name\" : \"John McClane\", \"avatar\" : \"http://avatar.example.com\", \"country\" : \"UK\", \"language\" : \"en\", \"api_version\" : 1 }, \"subscribed\" : false }");
System.out.println(((String)root.get("event")));
示例 2
//import java.util.ArrayList;
//import org.bson.Document;
Document root = Document.parse("{ \"event\" : \"message\", \"message\" : { \"type\" : \"text\", \"text\" : \"a message to the service\", \"location\" : { \"lat\" : 12.34, \"lon\" : 12.34 } } }");
System.out.println(((String)root.get("event")));
我做了三種方法。 首先是按照您的建議進行 - 解析 JSON,檢查類型,然后創建 object。 使用字符串解析器時要非常小心,因為您可能有也可能沒有新行之類的東西。 相反,請執行以下操作:
ObjectMapper objectMapper = new ObjectMapper();
JsonNode jsonNode = objectMapper.readTree(eventString);
String eventType = jsonNode.get("event").asText();
if( eventType.equalsIgnoreCase("conversation_started")) {
// create ConversationStarted object using something like:
ConversationStarted conversationStarted = objectMapper.readValue( eventString, ConversationStarted.class );
}
當然,這要求所有類都有一個具體的 POJO 以允許反序列化。
另一種方法是做許多其他編程語言所做的事情,並擁有一個鍵/值 map。 有幾種方法可以做到這一點。 一種是使用 Jackson 庫:
Map<String, Object> map = objectMapper.readValue(eventString, new TypeReference<Map<String,Object>>(){});
Map<String, Object> user = (Map<String, Object>) map.get("user");
System.out.println( "conversation started - avatar is " + user.get("avatar"));
這樣您就可以繞過 Map 並根據需要進行提取。 請注意,您仍然需要了解 JSON 的結構,但您不需要 POJO。
最后是第二種解決方案的變體。 使用JSONPath ,您可以直接提取您需要的內容。 同樣,您需要先查看您擁有的事件類型。 就像是:
if( JsonPath.read(eventString, "$.event").equals("conversation_started") ) {
String avatar = JsonPath.read(eventString, "$.user.avatar");
System.out.println("conversation started - avatar is " + avatar);
}
最后兩種方法要求您一次提取一個值,如圖所示。 第一個解決方案為您提供了一個完整的 object 可供使用。 您可以自行決定什么在您的環境中最有效。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.