2017-05-06 3 views
0

Ich habe einen Beispiel-JSON wie folgt. Ich muss dieses Objekt einem anderen JSON-Format zuordnen, das für die Benutzeroberfläche kanonisch ist (verschiedene Aufträge von verschiedenen Anbietern erhalten und sie zu einem gemeinsamen UI-Format zusammenfassen).JSON-Elemente mit Nummerierung als Teil des Elementnamens

Wenn ich POJOs erzeuge, erzeugt es Order_1, Order_2 ... Klassen unter der äußeren Klasse, die schmutzig aussieht. Und während der Entwicklungszeit kann ich möglicherweise nicht voraussagen, wie viele Bestellungen während der Spitzenzeiten kommen. Wie gehe ich dieses Problem an?

Mein Endergebnis sollte in der Lage sein, diesen JSON dem Ziel-JSON zuzuordnen, wo wiederholbare Elemente Arrays sind.

{ 
    "TotalOrders": 6, 
    "Order_1": { 
     "Item_1": { 
      "item": "Shirt", 
      "Quantity": 2 
     }, 
     "Item_2": { 
      "item": "Jeans", 
      "Quantity": 2 
     } 

    }, 
    "Order_2": { 
     "Item_1": { 
      "item": "Caps", 
      "Quantity": 2 
     }, 
     "Item_2": { 
      "item": "Bags", 
      "Quantity": 2 
     }, 
     "Item_3": { 
      "item": "Chains", 
      "Quantity": 2 
     } 
    }, 
    "Order_3": { 
     "Item_1": { 
      "item": "Watches", 
      "Quantity": 2 
     }, 
     "Item_2": { 
      "item": "Rings", 
      "Quantity": 2 
     }, 
     "Item_3": { 
      "item": "Perfumes", 
      "Quantity": 2 
     }, 
     "Item_4": { 
      "item": "Deo", 
      "Quantity": 1 
     } 
    }, 
    "Order_4": { 
     "Item_1": { 
      "item": "Cans", 
      "Quantity": 2 
     }, 
     "Item_2": { 
      "item": "Tubes", 
      "Quantity": 2 
     }, 
     "Item_3": { 
      "item": "Tents", 
      "Quantity": 2 
     } 
    }, 
    "Order_5": { 
     "Item_1": { 
      "item": "Butter", 
      "Quantity": 2 
     }, 
     "Item_2": { 
      "item": "Jam", 
      "Quantity": 2 
     }, 
     "Item_3": { 
      "item": "Bread", 
      "Quantity": 2 
     } 
    }, 
    "Order_6": { 
     "Item_1": { 
      "item": "DVD", 
      "Quantity": 2 
     }, 
     "Item_2": { 
      "item": "Floppy", 
      "Quantity": 2 
     }, 
     "Item_3": { 
      "item": "Cables", 
      "Quantity": 2 
     } 
    } 
} 

Antwort

0

Dies kann mit einem custom deserializer gelöst werden. Allerdings müssen Sie die JSON in Jackson's tree model parsen und ich finde die Arbeit mit dem Baummodell und Jackson sehr umständlich und nicht intuitiv.

So ist eine Alternative, Jacksons anySetter Feature zu verwenden, das eine annotierte Methode ist, die alle "unknown" Eigenschaften erhält. Der Vorteil gegenüber benutzerdefinierten Deserialisierer ist, dass Sie den JSON bereits in eine Map geparst haben, die viel einfacher zu durchlaufen und zu verarbeiten ist.

Hier ist ein Beispiel, das eine beliebige Anzahl von Bestellungen und Artikeln in POJO mit Arrays parsen wird. Ich habe Arrays verwendet, da diese einfacher zu verarbeiten sind, wenn der Zugriff über Indizes erfolgt.

import java.io.*; 
import java.util.*; 
import java.util.stream.*; 

import com.fasterxml.jackson.annotation.*; 
import com.fasterxml.jackson.databind.*; 

public class OrderList 
{ 
    private Order[] orders = null; 
    @JsonProperty("TotalOrders") 
    private int totalOrders = -1; 

    public static class Order 
    { 
     private OrderedItem[] items = null; 

     public OrderedItem[] getItems() { return items; } 

     @Override 
     public String toString() 
     { 
      return "Order:" + Arrays.toString(getItems()); 
     } 
    } 

    public static class OrderedItem 
    { 
     public String item; 
     public int quantity; 

     public OrderedItem() {} 
     public OrderedItem(String item, int quantity) 
     { 
      setItem(item); 
      setQuantity(quantity); 
     } 

     public String getItem() { return item; } 
     public void setItem(String newItem) { item = newItem; } 

     public int getQuantity() { return quantity; } 
     public void setQuantity(int newQty) { quantity = newQty; } 

     @Override 
     public String toString() 
     { 
      return "OrderedItem:{" + getItem() + "," + getQuantity() + "}"; 
     } 
    } 

    // all properties exepct totalOrders will be directed here 
    @SuppressWarnings("unchecked") 
    @JsonAnySetter 
    public void setOrders(String key, Object value) 
    { 
     // initialize orders array according to totalOrders 
     if (orders == null && totalOrders > 0) orders = new Order[totalOrders]; 
     // parse order idx from property name 
     int parseOrderIdx = -1; 
     if (key != null && key.startsWith("Order_")) { 
      parseOrderIdx = Integer.parseInt(key.split("_")[1]); 
     } 
     if (orders == null || parseOrderIdx < 1 || parseOrderIdx > orders.length) { 
      System.err.println("ERROR in parsing totalOrders and/or order idx"); 
      return; 
     } 

     // java requires final variable to be used in lambda expr. 
     final int orderIdx = parseOrderIdx; 
     orders[orderIdx-1] = new Order(); 
     // value arg is map of items 
     Map<String, Object> items = (Map<String, Object>)value; 
     orders[orderIdx-1].items = new OrderedItem[items.size()]; 
     IntStream.rangeClosed(1, items.size()).forEach(itemIdx -> { 
      Map<String, Object> item = (Map<String, Object>)items.get("Item_" + itemIdx); 
      if (item == null) { 
       System.err.println("ERROR in parsing item Item_" + itemIdx + " order Order_" + orderIdx); 
       return; 
      } 
      orders[orderIdx-1].items[itemIdx-1] = 
        new OrderedItem((String)item.get("item"), (Integer)item.get("Quantity")); 
     }); 
    } 

    public static void main(String[] args) 
    { 
     ObjectMapper mapper = new ObjectMapper(); 
     try (InputStream is = new FileInputStream("C://Temp/xx.json")){ 
      OrderList ol = mapper.readValue(is, OrderList.class); 
      System.out.println(Arrays.toString(ol.orders)); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 
Verwandte Themen