У меня есть строка JSON, и я конвертирую ее в JSONObject.
Я хочу получить определенные данные из JSONObject, и каждый раз, когда JSONObject меняет свою структуру, иногда он находится в массиве внутри JSON, а иногда нет. пример: в первый раз JSON приходит вот так
{
"id": "1",
"Name": "Jack",
"Value": {
"data": [
{"time": "2023", "age": "22"}
]
}}
второй раз
{
"age": "22",
"time": "2023",
"Value": {
"data": [
{"Name": "Jack", "id": "1" }
]
}}
если я хочу получить имя в первом JSON
jsonObject.getString("Name")
а для второго я бы использовал
jsonObject.getJSONArray("data").getJSONObject(0).getString("Name")
есть ли способ получить значение динамически независимо от того, где находятся ключи?
Если ваш API исходит от другой команды или внешнего поставщика, первое, что я бы посоветовал вам, — это четко определить контракт. В противном случае вы можете использовать метод isNull(String key)
из JSONObject
, чтобы проверить, существует ли ключ или нет.
Пример здесь:
JSONObject jsonObject = new JSONObject(YOUR_JSON_STRING);
String nameValue;
if (jsonObject.isNull("Name")) {
nameValue = jsonObject.getJSONObject("Value")
.getJSONArray("data")
.getJSONObject(0)
.getString("Name");
} else {
nameValue = jsonObject.getString("Name");
}
System.out.println(nameValue);
Если строки JSON всегда одинаковы, вы можете попробовать небольшой метод синтаксического анализатора, как показано ниже. Он возвращает карту ключ/значение (строка/объект):
public static java.util.Map<String, Object> mapJsonObject(String jsonString) {
String json = jsonString
.replaceAll("(?i)[\\[\\]\\{\\}\"]|\"?value\"?:|\"?data\"?:|\n?", "")
.replaceAll("\\s+", " ");
String[] keyValueParts = json.split("\\s*,\\s*");
java.util.Map<String, Object> map = new java.util.HashMap<>();
for (String str : keyValueParts) {
String[] pts = str.split("\\s*:\\s*");
map.put(pts[0].trim(), pts[1]);
}
return map;
}
Использовать:
String jsonString = "{\n"
+ " \"id\": \"1\",\n"
+ " \"Name\": \"Jack\",\n"
+ " \"Value\": {\n"
+ " \"data\": [\n"
+ " {\"time\": \"2023\", \"age\": \"22\"}\n"
+ " ]\n"
+ "}}";
java.util.Map<String, Object> map = mapJsonObject(jsonString);
System.out.println(map);
В окне консоли появится:
{id=1, time=2023, age=22 , Name=Jack}
Вы можете рассмотреть библиотеку Josson.
https://github.com/octomix/josson
Десериализация
Josson josson1 = Josson.fromJsonString(
"{" +
" \"id\": \"1\"," +
" \"Name\": \"Jack\"," +
" \"Value\": {" +
" \"data\": [" +
" {\"time\": \"2023\", \"age\": \"22\"}" +
" ]" +
" }" +
"}");
Josson josson2 = Josson.fromJsonString(
"{ " +
" \"age\": \"22\"," +
" \"time\": \"2023\"," +
" \"Value\": {" +
" \"data\": [" +
" {\"Name\": \"Jack\", \"id\": \"1\" }" +
" ]" +
" }" +
"}");
Запрос
*()
— это многоуровневый поиск по подстановочным знакам. Он возвращает первый разрешимый элемент.
System.out.println(josson1.getString("coalesce(Name, *().Name)"));
// Output: Jack
System.out.println(josson2.getString("coalesce(Name, *().Name)"));
// Output: ["Jack"]
// It is because "Name" is inside array "data".
System.out.println(josson1.getString("coalesce(Name, *().Name).first()"));
// Output: Jack
System.out.println(josson2.getString("coalesce(Name, *().Name).first()"));
// Output: Jack
// Added function first() to extract the value.
спасибо, я сделал ручной поиск на разных уровнях, попробую в следующий раз.
спасибо, это помогло мне проверить значения.