将没有引号的json字符串转换为映射

时间:2016-04-12 19:56:48

标签: java json jackson mapper

我有一个Json格式的字符串,只有没有键或值被引号括起来。例如,我有这个:

String json = "{name: Bob, state: Colorado, Friends: [{ name: Dan, age: 23 }, {name: Zane, age: 24 }]}"

我希望这会成为一个看起来像这样的地图:

Map<String, Object> friend1Map = new HashMap<>();
friend1Map.put("name", "Dan");
friend1Map.put("age", 23);

Map<String, Object> friend2Map = new Hashmap<>();
friend2Map.put("name", "Zane");
friend2Map.put("age", 24);

Map<String, Object> newMap = new HashMap<>();
newMap.put("name", "Bob");
newMap.put("state", "Colorado");
newMap.put("Friends", Arrays.asList(friend1Map, friend2Map));

我尝试了以下两种方法:

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

这会抛出错误,说:

Unexpected character ('n'): was expecting double-quote to start field name

然后我尝试更改mapper的配置:

mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
mapper.readValue(json, new TypeReference<Map<String, Object>>() {});

但这引发了一个错误说:

com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'Bob': was expecting ('true', 'false' or 'null')
at [Source: {name: Bob, state: Colorado, Friends: [{ name: Dan, age: 23 }, {name: Zane, age: 24 }]}; line: 1, column: 11]

当引号未包含在json字符串中时,有没有办法获取此Map?

5 个答案:

答案 0 :(得分:3)

自Java 15起

注意:我们希望Java 15将按原样支持未转义的双引号:

var json = """
        {"name": "Bob", "state": "Colorado", "Friends": [{ "name": "Dan", "age": 23 }, {"name": "Zane", "age": 24 }]} """;

more details


自GSON v2.8.6起

具有jackson fastxml的ObjectMapper不支持不带引号的值,但GSON可以:

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.JsonParser;

  JsonNode json = json("{"
      + "  name: Bob,      "
      + "  state: Colorado,"
      + "  Friends: [      "
      + "    {"
      + "      name: Dan,  "
      + "      age: 23     "
      + "    },"
      + "    {"
      + "      name: Zane, "
      + "      age: 24     "
      + "     }"
      + "  ],"
      + "  extra: \"text with spaces or colon(:) must be quoted\""
      + "}");

  Map m = new ObjectMapper().convertValue(json, Map.class);

JsonNode json(String content) throws IOException {

  String canonicalFormat = JsonParser.parseString(content).toString();
  return json.readTree(canonicalFormat);
}

埃里尔·杰森

在v2.8.6之前,GSON没有静态parseString方法。因此,您应该使用(在更高版本中已弃用)实例方法:

JsonNode json(String content) throws IOException {

  String canonicalFormat = new JsonParser().parse(content).toString();
  return json.readTree(canonicalFormat);
}

答案 1 :(得分:2)

回答你的问题:没有安全方式获取你的JSON - 顺便说一下,这不是JSON,因为它无效 - 转换为Map<String, Object>

让我详细说明一下(为什么不能安全地解析它?): 想象一下像这样的“JSON”:

{
    this is my key: and here's my value and it even has a colon:
}

有效的JSON看起来像这样

{
    "this is my key": "and here's my value and it even has a colon:"
}

使用引号,解析器可以安全地确定键和值。如果没有它们,解析器就会丢失。

答案 2 :(得分:1)

如果Json输入无效,它将无法解析Json输入,所以答案是否定的。

在这里测试你的Json:http://jsonlint.com/

在纠正Json输入后,你可以这样做:

max-width

将打印:

  

鲍勃

答案 3 :(得分:0)

您可以使用以下代码预处理json字符串,然后解析它。

String str = ("{requestid:\"55275645.f213506045\",timestamp:\"213506045\",bidnumber:\"55275645\",checkcode:\"1f6ad033de64d1c6357af34d4a38e9e3\",version:\"1.0\",request:{token:ee4e90c2-7a8b-4c73-bd48-1bda7e6734d5,referenceId:0.5878463922999799}}");
    str = (str.replaceAll(":\"?([^{|^]*?)\"?(?=[,|}|\\]])",":\"$1\"").replaceAll("\"?(\\w+)\"?(?=:)","\"$1\""));
    JSONObject obj = JSON.parseObject(str);
    System.out.println(obj.getJSONObject("request").getString("token"));

答案 4 :(得分:0)

我们可以使用Apache Commons和Guava基础库将此类json转换为Map。 例: 输入-{name = jack,id = 4} 输出-地图(名称=插孔,ID = 4)

import com.google.common.base.Splitter;
import org.apache.commons.lang.StringUtils;

String input = StringUtils.substringBetween(value, "{", "}");
Map<String, String> map = 
Splitter.on(",").withKeyValueSeparator("=").split(input);