Convert json string without quotes into a map

user2869231 picture user2869231 · Apr 12, 2016 · Viewed 18.9k times · Source

I have a string that is in Json format, only none of the keys or values are surrounded by quotes. For example, I have this:

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

I want this to become a map that looks like so:

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

I have tried the following two methods:

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

This will throw an error, saying:

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

Then I tried changing the config of mapper:

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

But this threw an error saying:

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]

Is there a way of getting this Map when quotes aren't included in the json string?

Answer

epox picture epox · Mar 12, 2020

SINCE Java 15

NOTE: we expect Java 15 will support unescaped double-quotes as is:

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

more details


SINCE GSON v2.8.6

ObjectMapper with jackson fasterxml doesn't support values without quotes, but GSON does:

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

EARLIER GSON

Before v2.8.6 GSON didn't have the static parseString method. So you should use the (deprecated in higher versions) instance method:

JsonNode json(String content) throws IOException {

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