2017-04-12 75 views
0

我有一個抽象類具有許多具體的實現:解析動態包裹JSON陣列

public abstract Ticket { 
    private Long id; 
    private Currency fine; 
    ... 
} 

public class SpeedingTicket extends Ticket { 
    public Currency getFine(){ 
     // Expensive! 
     ... 
    } 
} 

public class ParkingTicket extends Ticket { 
    public Currency getFine(){ 
     // Eh, not so bad 
     ... 
    } 
} 

當混凝土類被序列化爲JSON,它被包裹着的類簡單的名稱(speedingTickets或parkingTickets):

"_embedded": { 
    "speedingTickets" : 
    [{ 
     "id":1, 
     "fine": "$190", 
     ..., 
    }, 
    { 
     "id":2, 
     "fine": "$100", 
     ..., 
    }] 
} 

"_embedded": { 
    "parkingTickets" :[{ 
     "id":100, 
     "fine": "$15", 
     ..., 
    }] 
} 

因爲我不知道,在運行時,其中Ticket實現我收到回來,我怎麼能解析JSON使用JSON Response API給定的數組是用具體實現簡單名稱包裝?

我有一個破解我JSON的字符串值,並做它的字符串操作(substring,indexOf等),只返回大括號之間的內容(「[...]」)。我知道有一個更好的方式來做到這一點...



經過一番研究,我想我會嘗試以下的明天,看看它的工作原理:

JsonNode rootNode = mapper.readTree(jsonResponse); 
String classImpl = Iterables.get(rootNode.get("_embedded").fields(), 0).textValue() 

我然後可以說List<Ticket> tickets = response.readAsList(jsonResponse, "_embedded",classImpl)這應該允許我將JSON解析爲列表

+0

的可能的複製[GSON - 讀取的值與兩個不同的密鑰(http://stackoverflow.com/questions/35739713/gson-read-a-value-with-two-different-keys) – Bharatesh

+0

我的問題是關於解析具有動態生成的關鍵字的json aray。你的鏈接是關於屬性。 – Dan

回答

-1

JSON對象是一組無用的鍵/值對。 JSON數組是值的有序集合。這些值本身可以是對象或數組。

在java中很容易解析JSON與org.json庫https://github.com/stleary/JSON-java

短例如如何解析JSON數組:

String str = "{ \"number\": [3, 4, 5, 6] }"; 
JSONObject obj = new JSONObject(str); 
JSONArray arr = obj.getJSONArray("number"); 
for (int i = 0; i < arr.length(); i++) 
    System.out.println(arr.getInt(i)); 
+0

我想你錯過了我的問題。如果你知道「數字」是關鍵,那麼你的上述工作是什麼。在我的情況下,關鍵是動態的(由實施類的簡單名稱決定) – Dan

0

如果你使用傑克遜(如您的標籤提示),你想使用Polymorphic Deserialization - 這正是知道如何反序列化到正確的子類型的問題。

例如:

@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@class") 
class { } 

這本質上確實是在你的JSON包含類的名字,所以解串器有足夠的信息來正確選擇個子類的實例。類似這樣的:

"_embedded": { 
    "parkingTickets" :[{ 
     "_type": "ParkingTicket.class", 
     "id":100, 
     "fine": "$15", 
     ..., 
    }] 
} 
+0

是的,我正在這樣做。我正在使用@JsonTypeInfo以及現有的屬性值來確定實現。然而,我的問題與我正在進行的功能單元測試有關。我通過API進行模擬調用,但是由於關鍵字('parkingTickets'或'speedingTickets')基於其實現而改變,所以我無法將響應轉回到對象中。 – Dan

+0

如果您在您的問題中提供了更全面的摘要,這將有所幫助。我假設你是指基於API實現的關鍵更改?如果你同時控制API和客戶端,你應該把模型放在一個共享庫中,這樣兩端的序列化/反序列化肯定是一樣的。如果你不控制API,你可以做的最好的事情就是將它編碼到文檔中。 – nighthawk454

+0

我的意思是基於具體類名稱的關鍵更改。因此,json中的關鍵「speedingTickets」由「SpeedingTicket」實現創建。與'ParkingTickets'一樣。 「_embedded」之後的值根據實現類名稱 – Dan

0

您可以通過檢查響應包含的變量來檢查類型。

JSONObject jsonObj = new JSONObject(response); 
if(jsonObj.has("speedingTickets")){ 
    // parse speedingTickets 
}else if(jsonObj.has("parkingTickets")){ 
    // parse parkingtickets 
} 
+0

我想過這樣做,但是有20多種實現類型。我不認爲這將是大規模的實用 – Dan