簡體   English   中英

如果我在解析之前不知道所有 Z466DEEC76ECDF2456D38571F6Z 字段,如何將 JSON 轉換為 Java object?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM