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中,我希望能够拿起该字符串,然后做类似的事情:

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>

拥有您的Person类并使用GSON,您可以简单地做:

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

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

但要小心:您的JSON字符串无效。它不应从"people:"开始。

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,则您有一个对象。否则,这是一个简单的值。

您可以使用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>(){});

现在,它被视为地图;

完整示例:

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

输出:收银员布局

最新更新