Java:使用未知键解析JSON来映射

时间:2019-05-10 07:13:57

标签: java json

在Java中,我需要使用JSON(下面的示例)以及一系列任意键,并产生Map<String, String>。我想使用一个标准的,长期支持的JSON库进行解析。但是,我的研究表明,这些库是为反序列化为Java类而设置的,您需要事先了解这些字段。我只需要构建地图。

实际上,这要复杂得多,因为任意键不是JSON的顶层;它们仅作为prefs的子对象出现。其余的都是已知的,可以放入预定义的类中。

{
    "al" : { "type": "admin", "prefs" : { "arbitrary_key_a":"arbitary_value_a", "arbitrary_key_b":"arbitary_value_b"}},
    "bert" : {"type": "user", "prefs" : { "arbitrary_key_x":"arbitary_value_x", "arbitrary_key_y":"arbitary_value_y"}},
    ...
}

在Java中,我希望能够使用该String并执行类似的操作:

people.get("al").get("prefs"); // Returns Map<String, String>

我该怎么做?我想使用一个标准的,受支持的解析器,避免出现异常,并使事情保持简单。


更新

@kumensa指出,这比看起来要难。能够做到:

people.get("al").getPrefs(); // Returns Map<String, String>
people.get("al").getType();  // Returns String

一样好。

那应该将JSON解析为类似的内容:

public class Person {
    public String type;
    public HashMap<String, String> prefs;
}
// JSON parsed to:
HashMap<String, Person>

3 个答案:

答案 0 :(得分:1)

有了Person类并使用Gson,您可以轻松地做到:

final Map<String, Person> result = new Gson().fromJson(json, new TypeToken<Map<String, Person>>() {}.getType());

然后,通过prefs来检索people.get("al").getPrefs();

但是要小心:您的json字符串无效。它不应该以{{1​​}}开头。

答案 1 :(得分:0)

您可以使用Jackson lib实现此目的。 将以下内容放入pom.xml。

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.8</version>
</dependency>

请参考以下说明相同的代码段。

ObjectMapper mapper = new ObjectMapper();
HashMap<String, Object> people = mapper.readValue(jsonString, new TypeReference<HashMap>(){});

现在,它反序列化为Map;

完整示例:

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

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class testMain {

    public static void main(String[] args) throws JsonParseException, JsonMappingException, IOException {

        String json = "{\"address\":\"3, 43, Cashier Layout, Tavarekere Main Road, 1st Stage, BTM Layout, Ambika Medical, 560029\",\"addressparts\":{\"apartment\":\"Cashier Layout\",\"area\":\"BTM Layout\",\"floor\":\"3\",\"house\":\"43\",\"landmark\":\"Ambika Medical\",\"pincode\":\"560029\",\"street\":\"Tavarekere Main Road\",\"subarea\":\"1st Stage\"}}";

        ObjectMapper mapper = new ObjectMapper();
        HashMap<String, Object> people = mapper.readValue(json, new TypeReference<HashMap>(){});

        System.out.println(((HashMap<String, String>)people.get("addressparts")).get("apartment"));
    }

}

输出:收银台布局

答案 2 :(得分:0)

public static <T> Map<String, T> readMap(String json) {
    if (StringUtils.isEmpty(json))
        return Collections.emptyMap();

    ObjectReader reader = new ObjectMapper().readerFor(Map.class);
    MappingIterator<Map<String, T>> it = reader.readValues(json);

    if (it.hasNextValue()) {
        Map<String, T> res = it.next();
        return res.isEmpty() ? Collections.emptyMap() : res;
    }

    return Collections.emptyMap();
}

接下来要做的就是检查Object的类型。如果它是Map,则您有一个对象。否则,这是一个简单的值。