【问题标题】:Convert a List of json object to hashmap using jackson使用jackson将json对象列表转换为hashmap
【发布时间】:2016-06-17 18:00:41
【问题描述】:

有没有办法使用内置的 Jackson 功能使用 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;

【问题讨论】:

  • 请用双引号将所有属性名称都引用为有效的 JSON 对象。

标签: java jackson objectmapper


【解决方案1】:

我建议手动进行。你只需要写几行。有点像

    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)。

【讨论】:

  • 然后就可以使用自定义反序列化器了。
  • 是的...我也想写一个,但是正如@neal 指定的那样,有没有办法避免使用中间对象....如果不使用中间类,我无论如何都找不到...
  • 如果我做对了,你想避免使用 CustomObject。您的 json 代表一个对象,而不是列表。所以杰克逊需要精确的模型来映射json。但是,您可以从 json 对象中提取列表,然后使用用户自定义反序列化器。 JsonNode node = mapper.readTree(json).path("list")
【解决方案2】:

先将list转化为map数组,再创建key和value的map。

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();
        }
    }
}

【讨论】:

    【解决方案3】:

    我认为您必须编写自定义反序列化程序。这是一个选项:

        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;
                }
    
            }
    

    【讨论】:

    • 我们可以避免使用 KeyValuePairs 吗??
    • 我认为您无法避免使用它。我相信杰克逊需要这门课来弄清楚如何通过反射来映射字段。为了得到结果,你要做的就是:CustomObject o = objectMapper.readValue(carJson, CustomObject.class); Map map = o.getCustomKeyValueMap();
    【解决方案4】:

    这个答案可能不是你要找的,当然不是一个简单的解决方案。这个帮助类读取输入文件就像它是 SAX-XML 解析器,不像 DOM-XML 解析器。

    我的用例是一个大型的“随机”结构化 json 文件和更新数据库对象。这永远不会将整个文档加载到 RAM 内存中。我不能使用强类型对象,所以选择了 hashmap 解决方案。

    这个循环输入文件,收集每个给定断点对象路径的字段值,调用处理函数。 Hashmap 具有 parent.entry.field=xxxxx 值,转储 keyval 对以查看命名语法。

    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();
        }
    

    (从我的应用程序中简化复制粘贴可能会引入语法错误)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-23
      • 2013-03-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多