Java 将JSON数组转换为HashMap<;字符串,对象>;使用jackson解析器

Java 将JSON数组转换为HashMap<;字符串,对象>;使用jackson解析器,java,hashmap,jackson,Java,Hashmap,Jackson,我正在使用:import com.fasterxml.jackson.databind* 我有一个json数组: {"nodes": [ {"blockId":"decision1422461296135","text":"hello"}, {"blockId":"Action1422461296640","text":"Action"}, {"blockId":"prompt1422461298089","text":"Prompt"} ]

我正在使用:import com.fasterxml.jackson.databind*

我有一个json数组:

{"nodes":
    [
     {"blockId":"decision1422461296135","text":"hello"},  
     {"blockId":"Action1422461296640","text":"Action"},  
     {"blockId":"prompt1422461298089","text":"Prompt"}
    ]
}
我想将上面的数组转换为
HashMap
,其中键是blockId,节点是一个POJO,其中包含id和文本字段

我宁愿不使用任何其他外部库


现在,我正在将
JSON数组
转换为节点的
数组
,然后遍历该数组以创建我想要的
HashMap
。我不认为这是优化的。我想在
ObjectMapper
解析JSON时创建
HashMap

您能按如下方式更改JSON结构吗:

{    
 "decision1422461296135":{"text":"hello"},  
 "Action1422461296640":  {"text":"Action"},  
 "prompt1422461298089":  {"text":"Prompt"}
}
Nodes类可以如下所示:

public class Nodes {
    private Map<String,Node> nodesMap;
}
公共类节点{
私有映射节点映射;
}

在深入了解Jackson序列化程序内部之后,以下是您想要的版本:

@JsonDeserialize(using = NodeDeserializer.class)
public class Nodes {
    private Map<String, Node> nodesMap;
    //getter/setter
}
@JsonDeserialize(使用=NodeDeserializer.class)
公共类节点{
私有映射节点映射;
//吸气剂/塞特
}
序列化程序:

public class NodeDeserializer extends JsonDeserializer<Nodes> {
    @Override
    public Nodes deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        Map<String, Node> nodes = new HashMap<>();
        p.getCurrentToken();//START_OBJECT
        p.nextToken();//FIELD_NAME
        p.nextToken();//START_ARRAY
        p.nextToken();//START_OBJECT
        while (p.getCurrentToken() != JsonToken.END_ARRAY) {
            p.nextToken();//blockId field
            p.nextToken();//blockId value
            String id = p.getValueAsString();
            p.nextToken();//text field
            p.nextToken();//text value
            String text = p.getValueAsString();
            p.nextToken();//END_OBJECT
            p.nextToken();//START_OBJECT?
            nodes.put(id, new Node().setBlockId(id).setText(text));
        }
        return new Nodes().setNodesMap(nodes);
    }
}
公共类NodeSerializer扩展JsonDeserializer{
@凌驾
公共节点反序列化(JsonParser p,DeserializationContext ctxt)引发IOException,JsonProcessingException{
映射节点=新的HashMap();
p、 getCurrentToken();//启动对象
p、 nextToken();//字段名称
p、 nextToken();//启动数组
p、 nextToken();//启动对象
while(p.getCurrentToken()!=JsonToken.END_数组){
p、 nextToken();//块ID字段
p、 nextToken();//块ID值
字符串id=p.getValueAsString();
p、 nextToken();//文本字段
p、 nextToken();//文本值
String text=p.getValueAsString();
p、 nextToken();//结束_对象
p、 nextToken();//启动对象?
nodes.put(id,new Node().setBlockId(id).setText(text));
}
返回新节点().setNodeMap(节点);
}
}
这应该包括你的要求。这个类不是
BeanDeserializer
,而是经过计算的,它只迭代一次


对于有效的json,它可以正常工作。我在Jackson 2.5.2上试过,你有没有测量过性能问题?你的阵列有多大?预优化是万恶之源。做一件简单的事情,只有当您有性能问题并且已经证明它来自于代码的这一部分时,才进行优化。我的猜测是,与实际读取JSON相比,将memoty中的数组转换为map是微不足道的。我想优化这段特定的代码,而不考虑数组的大小。假设这是一个面试问题,要求您优化转换。有没有一种方法可以通过jackson实现这一点(可能使用jackson注释)。我对采访的回答是:如果没有必要进行优化,则会浪费时间、金钱和精力,并且很有可能生成更复杂、更麻烦、更难维护的代码。为了公司和产品的利益,除非出现性能问题,否则我不会做任何事情,我通过将阵列转换为映射来衡量它。缺点是:忘了优化,我只想实现问题中的要求。你可以做你在自定义反序列化器中已经在做的事情。如果有任何其他注释可以执行您想要的操作,它将执行相同的操作:读取节点,将节点正确地放入HashMap,收集下一个节点。演出也一样。有关自定义反序列化程序的更多信息,请查看文档。这是一个很好的建议。我宁愿不改变json结构。