2016-03-04 3 views
4

Есть ли способ, чтобы использовать встроенные возможности Джексона, чтобы преобразовать список объектов JSON в HashMap с помощью JavaПреобразование списка объекта JSON в HashMap с помощью джексон

Объяснения: JSon структуры, что мне нужно, чтобы разобрать

{ 
    list:[ 
     { 
      keyId : 1, 
      keyLabel : "Test 1", 
      valueId: 34, 
      valueLabel: "Test Lable" 
     }, 
     { 
      keyId : 2, 
      keyLabel : "Test 2", 
      valueId: 35, 
      valueLabel: "Test Lable" 
     }, 
     { 
      keyId : 3, 
      keyLabel : "Test 3", 
      valueId: 36, 
      valueLabel: "Test Lable" 
     } 
    ] 
} 

объектная модель Я ожидаю,

class Key{ 
    int keyId; 
    String keyLable; 

    hashCode(){ 
    return keyId.hashCode(); 
    } 
} 

class Value{ 
    int valueId; 
    String valueLable; 

    hashCode(){ 
    return valueId.hashCode(); 
    } 
} 

Мне нужно преобразовать приведенный выше список JSon на карте, как это,

HashMap<Key,Value> map; 
+0

Пожалуйста двойные кавычки все имена свойств для этого, чтобы быть действительным объектом JSON. –

ответ

0

Я предлагаю сделать это вручную. Вам просто нужно написать несколько строк. Что-то, как

ObjectMapper jmap = new ObjectMapper(); 
    //Ignore value properties 
    List<Key> keys = jmap.readValue("[{}, {}]", jmap.getTypeFactory().constructCollectionType(ArrayList.class, Key.class)); 
    //Ignore key properties 
    List<Value> values = jmap.readValue("[{}, {}]", jmap.getTypeFactory().constructCollectionType(ArrayList.class, Value.class)); 

    Map<Key, Value> data = new HashMap<>(); 
    for (int i = 0; i < keys.size(); i++) { 
     data.put(keys.get(i), values.get(i)); 
    } 

Примечание: Существует несоответствие орфографии в вашем JSON и модели (valueLabel = valueLable!).

+0

Его не похожи на более чистый подход ко мне ...... – Ysak

+0

Тогда вы можете использовать пользовательский десериализатор. –

+0

Да ... Я также смотрю на письмо, но, как указано в @neal, есть способ избежать использования промежуточного объекта .... Я не мог найти так или иначе, не используя промежуточный класс ... – Ysak

0

Сначала преобразуйте список в массив карты, а затем создайте карту ключа и значения.

import java.io.IOException; 
import java.util.HashMap; 
import java.util.Map; 

import com.fasterxml.jackson.core.JsonGenerationException; 
import com.fasterxml.jackson.core.JsonParser; 
import com.fasterxml.jackson.core.type.TypeReference; 
import com.fasterxml.jackson.databind.JsonMappingException; 
import com.fasterxml.jackson.databind.JsonNode; 
import com.fasterxml.jackson.databind.ObjectMapper; 

public class JsonMapExample { 

    public static void main(String[] args) { 

     try { 

      ObjectMapper mapper = new ObjectMapper(); 
      String json = "{\"list\":[{\"keyId\":1,\"keyLabel\":\"Test 1\",\"valueId\":34,\"valueLabel\":\"Test Lable\"},{\"keyId\":2,\"keyLabel\":\"Test 2\",\"valueId\":35,\"valueLabel\":\"Test Lable\"},{\"keyId\":3,\"keyLabel\":\"Test 3\",\"valueId\":36,\"valueLabel\":\"Test Lable\"}]}"; 
      JsonNode node = mapper.readTree(json).path("list"); 
      JsonParser parser = mapper.treeAsTokens(node); 
      Map<String, Object>[] clients = parser.readValueAs(new TypeReference<Map<String, Object>[]>() { 
      }); 
      Map<Key, Value> result = new HashMap<Key, Value>(); 
      for (Map<String, Object> map : clients) { 
       int keyId = Integer.parseInt(map.get("keyId").toString()); 
       int valueId = Integer.parseInt(map.get("valueId").toString()); 
       result.put(new Key(keyId, map.get("keyLabel").toString()), 
         new Value(valueId, map.get("valueLabel").toString())); 
      } 
      System.out.println(result); 
     } catch (JsonGenerationException e) { 
      e.printStackTrace(); 
     } catch (JsonMappingException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 
0

Думаю, вам придется написать собственный десериализатор. Вот вариант:

public class CustomObject{ 
    private List<KeyValuePairs> list; 

    public List<KeyValuePairs> getList() { 
     return list; 
    } 
    public void setList(List<KeyValuePairs> list) { 
     this.list = list; 
    } 

    //Helper 
    public HashMap<CustomKey,CustomValue> getCustomKeyValueMap(){ 
     Map<CustomKey,CustomValue> map = new HashMap<CustomKey,CustomValue>(); 
     for(KeyValuePairs kvpair: list){ 
      map.put(new CustomKey(kvpair.getKeyId(),kvpair.getKeyLabel()), 
        new CustomValue(kvpair.getValueId(),kvpair.getValueLabel())); 
     } 
     return map; 
    } 
} 

    public class KeyValuePairs{ 
     private int keyId; 
     private String keyLabel; 
     private int valueId; 
     private String valueLabel; 

     //Getters and Setters 
     public int getKeyId() { 
      return keyId; 
     } 
     public void setKeyId(int keyId) { 
      this.keyId = keyId; 
     } 
     public String getKeyLabel() { 
      return keyLabel; 
     } 
     public void setKeyLabel(String keyLabel) { 
      this.keyLabel = keyLabel; 
     } 
     public int getValueId() { 
      return valueId; 
     } 
     public void setValueId(int valueId) { 
      this.valueId = valueId; 
     } 
     public String getValueLabel() { 
      return valueLabel; 
     } 
     public void setValueLabel(String valueLabel) { 
      this.valueLabel = valueLabel; 
     } 

    } 
     public class CustomKey{ 
      int keyId; 
      String keyLable; 

      public CustomKey(){ 

      } 

      public CustomKey(int keyId, String keyLable){ 
       this.keyId = keyId; 
       this.keyLable = keyLable; 
      } 

      public int getKeyId() { 
       return keyId; 
      } 
      public void setKeyId(int keyId) { 
       this.keyId = keyId; 
      } 
      public String getKeyLable() { 
       return keyLable; 
      } 
      public void setKeyLable(String keyLable) { 
       this.keyLable = keyLable; 
      } 

     }  



     public class CustomValue{ 
      int valueId; 
      String valueLable; 

      public CustomValue(){ 

      } 
      public CustomValue(int valueId, String valueLable){ 
       this.valueId = valueId; 
       this.valueLable = valueLable; 
      } 

      public int getValueId() { 
       return valueId; 
      } 
      public void setValueId(int valueId) { 
       this.valueId = valueId; 
      } 
      public String getValueLable() { 
       return valueLable; 
      } 
      public void setValueLable(String valueLable) { 
       this.valueLable = valueLable; 
      } 

     } 
+0

Можем ли мы избежать использования KeyValuePairs? – Ysak

+0

Я не думаю, что вы можете избежать этого. Я считаю, что Джексону нужен этот класс, чтобы выяснить, как отображать поля через отражение. Все, что вы сделали бы, чтобы получить результат, было бы что-то вроде: CustomObject o = objectMapper.readValue (carJson, CustomObject.class); Карта map = o.getCustomKeyValueMap(); – neal

0

Этот ответ может и не быть тем, что вы ищете, конечно, не простым решением. Этот вспомогательный класс читает входной файл, такой как SAX-XML-парсер, в отличие от парсера DOM-XML.

My usecase - это большой «случайный» структурированный json-файл и обновление объектов базы данных. Это никогда не загружает весь документ в оперативную память. Я не могу использовать сильно типизированные объекты, поэтому пошел на решение hashmap.

Этот один вводит входной файл, который собирает значения полей для каждого объекта объекта точки останова, вызывает функцию обработчика. В Hashmap есть parent.entry.field = xxxxx значения, пары дампов дампа, чтобы увидеть синтаксис именования.

import java.util.Iterator; 
import java.util.LinkedHashMap; 
import java.util.Map; 
import java.util.Stack; 
import com.fasterxml.jackson.core.JsonParser; 
import com.fasterxml.jackson.core.JsonToken; 

public class JSONHandler { 
    private Stack<String> parents; 
    private String cachedParent; 
    private Map<String,String> entry; 
    private Map<String,String> parentEntry; 

    public JSONHandler(JSONHandler.EntryHandler handler, JsonParser jsonP, 
         String path) throws Exception { 
     parents = new Stack<String>(); 
     entry = new LinkedHashMap<String,String>(16);// new HashMap<String,String>(16); 
     parentEntry = new LinkedHashMap<String,String>(8); 

     if (!path.endsWith(".")) path+="."; 

     boolean isParent=true; 
     int arrayIdx=-1; 
     cachedParent=""; 
     JsonToken token; 
     boolean doProcess=true; 
     while ((token=jsonP.nextToken()) != null) { 
      String name = jsonP.getCurrentName(); 
      if (token == JsonToken.START_OBJECT) { 
       parents.push(name); 
       if (cachedParent.equals(path)) { 
        entry.clear(); // start new target entry 
        arrayIdx=0; 
        if (!parentEntry.isEmpty()) entry.putAll(parentEntry); 
        isParent=false; 
       } else if (!cachedParent.startsWith(path)) { 
        isParent=true; // add fields to parent entry 
       } 
       cachedParent = implodeStack(parents); 
      } else if (token == JsonToken.END_OBJECT) { 
       parents.pop(); 
       cachedParent = implodeStack(parents); 
       if (cachedParent.equals(path)) { 
        doProcess=handler.process(entry); 
        arrayIdx=-1; 
        if (!doProcess) break; 
       } else if (name==null && cachedParent.startsWith(path)) { 
        String sArrayIdx = parents.peek(); // increment arrayIndex+1 
        parents.set(parents.size()-1, ""+(Integer.parseInt(sArrayIdx)+1)); 
        cachedParent = implodeStack(parents); 
       } else if (!cachedParent.startsWith(path)) { 
        Iterator<Map.Entry<String,String>> iter=parentEntry.entrySet().iterator(); 
        while(iter.hasNext()) { 
         Map.Entry<String,String> me = iter.next(); 
         if (me.getKey().startsWith(cachedParent)) 
          iter.remove(); 
        } 
       } 
      } else if (token == JsonToken.START_ARRAY) { 
       parents.push(name); 
       if (arrayIdx>-1) parents.push(String.valueOf(arrayIdx)); 
       cachedParent = implodeStack(parents); 
      } else if (token == JsonToken.END_ARRAY) { 
       parents.pop(); 
       if (arrayIdx>-1) { 
        parents.pop(); 
        arrayIdx=0; 
       } 
       cachedParent = implodeStack(parents); 
      } else if (token == JsonToken.FIELD_NAME) { 
       //System.out.println("field="+jsonP.getCurrentName()); 
      } else { 
       String value; 
       if (token == JsonToken.VALUE_NULL) value = null; 
       else if (token == JsonToken.VALUE_TRUE) value = "1"; 
       else if (token == JsonToken.VALUE_FALSE) value = "0"; 
       else value = jsonP.getText(); 
       if (cachedParent.startsWith(path)) { 
        if (name==null && arrayIdx>-1) { 
         // simple array "values":["aa","bb","cc"], 
         // write parent.item.values.0=aa, .1=bb, .2=cc 
         parents.set(parents.size()-1, ""+(arrayIdx++)); 
         cachedParent = implodeStack(parents); 
         entry.put(cachedParent.substring(0,cachedParent.length()-1), value); 
        } else 
         entry.put(cachedParent+name, value); 
       } else if (isParent) { 
        parentEntry.put(cachedParent+name, value); 
       } 
      } 
     } 
    } 

    private String implodeStack(Stack<String> stack) { 
     StringBuilder sb = new StringBuilder(); 
     for(String value : stack) { 
      if (value!=null) 
       sb.append(value + "."); 
     } 
     return sb.toString(); 
    } 


    public static interface EntryHandler { 
     public void startDocument() throws Exception; 
     public boolean process(Map<String,String> entry) throws Exception; 
    } 

} 

Пример клиента

JSONHandler.EntryHandler handler = new JSONHandler.EntryHandler() { 
     public void startDocument() throws Exception {}; 
     public boolean process(Map<String,String> entry) throws Exception { 
      for(String key : entry.keySet()) 
       System.out.println(key+"="+entry.get(key)); 
      return true; 
     } 
    }; 

    JsonFactory jsonF = new JsonFactory(); 
    jsonF.enable(JsonParser.Feature.AUTO_CLOSE_SOURCE); 
    JsonParser jsonP = jsonF.createParser(file); 
    try { 
     handler.startDocument(); 
     new JSONHandler(handler, jsonP, "list"); 
    } finally { 
     jsonP.close(); 
    } 

(CopyPaste упрощая из моего приложения может иметь ввести синтаксические ошибки)