J'ai une chaîne au format Json, seule aucune des clés ou valeurs n'est entourée de guillemets. Par exemple, j'ai ceci:
String json = "{name: Bob, state: Colorado, Friends: [{ name: Dan, age: 23 }, {name: Zane, age: 24 }]}"
Je veux que cela devienne une carte qui ressemble à ceci:
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));
J'ai essayé les deux méthodes suivantes:
ObjectMapper mapper = new ObjectMapper();
mapper.readValue(json, new TypeReference<Map<String, Object>>() {});
Cela générera une erreur, disant:
Unexpected character ('n'): was expecting double-quote to start field name
Ensuite, j'ai essayé de changer la configuration du mappeur:
mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
mapper.readValue(json, new TypeReference<Map<String, Object>>() {});
Mais cela a jeté une erreur en disant:
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]
Existe-t-il un moyen d'obtenir cette carte lorsque les guillemets ne sont pas inclus dans la chaîne json?
Pour répondre à votre question: il n'y a pas sûr moyen d'obtenir votre JSON - qui n'est pas JSON d'ailleurs, car il n'est pas valide - converti en Map<String, Object>
.
Permettez-moi de développer un peu (pourquoi ne peut-il pas être analysé en toute sécurité?): Imaginez un "JSON" comme ceci:
{
this is my key: and here's my value and it even has a colon:
}
Un JSON valide ressemblerait à quelque chose comme ceci
{
"this is my key": "and here's my value and it even has a colon:"
}
Avec les guillemets, un analyseur peut déterminer en toute sécurité les clés et les valeurs. Sans eux, un analyseur est perdu.
L'ObjectMapper ne pourra pas analyser l'entrée Json si elle n'est pas valide, donc la réponse est non.
Testez votre Json ici: http://jsonlint.com/
Après avoir corrigé l'entrée Json, vous pouvez faire:
ObjectMapper ob = new ObjectMapper();
ob.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
String json = "{name: \"Bob\", state: \"Colorado\", Friends: [{ name: \"Dan\", age: 23 }, {name: \"Zane\", age: 24 }]}";
Map<String, ObjectNode> theMap = ob.readValue(json, Map.class);
System.out.println(theMap.get("name"));
Imprime:
Bob
vous pouvez utiliser le code suivant pour prétraiter la chaîne json, puis l'analyser.
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"));
REMARQUE: à partir de Java 14 (version de mars 2020), vous pouvez utiliser des guillemets non échappés tels quels:
var json = """
{"name": "Bob", "state": "Colorado", "Friends": [{ "name": "Dan", "age": 23 }, {"name": "Zane", "age": 24 }]} """;
ObjectMapper avec jackson Fastxml ne prend pas en charge les valeurs sans guillemets, mais GSON le fait:
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);
}
Avant la v2.8.6, GSON n'avait pas la méthode statique parseString. Vous devez donc utiliser la méthode d'instance (obsolète dans les versions supérieures):
JsonNode json(String content) throws IOException {
String canonicalFormat = new JsonParser().parse(content).toString();
return json.readTree(canonicalFormat);
}
Nous pouvons convertir un tel json en une carte en utilisant les bibliothèques de base Apache Commons et Guava. Exemple: Entrée - {name = jack, id = 4} Output - Map (name = jack, 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);