如何解析嵌套 JSON 结果中的动态 JSON 键?
Posted
技术标签:
【中文标题】如何解析嵌套 JSON 结果中的动态 JSON 键?【英文标题】:How to parse a dynamic JSON key in a Nested JSON result? 【发布时间】:2011-11-10 08:46:58 【问题描述】:我有一个以下格式的 JSON 结果,JSON Lint 将其显示为“有效响应”。
我的问题是:我如何访问“question_mark”的内容,因为“141”、“8911”等都是动态值?
我用于访问“产品”值的示例代码。
//Consider I have the first <code>JSONObject</code> of the "search_result" array and
//I access it's "product" value as below.
String product = jsonObject.optString("product"); //where jsonObject is of type JSONObject.
//<code>product<code> now contains "abc".
JSON:
"status": "OK",
"search_result": [
"product": "abc",
"id": "1132",
"question_mark":
"141":
"count": "141",
"more_description": "this is abc",
"seq": "2"
,
"8911":
"count": "8911",
"more_desc": "this is cup",
"seq": "1"
,
"name": "some name",
"description": "This is some product"
,
"product": "XYZ",
"id": "1129",
"question_mark":
"379":
"count": "379",
"more_desc": "this is xyz",
"seq": "5"
,
"845":
"count": "845",
"more_desc": "this is table",
"seq": "6"
,
"12383":
"count": "12383",
"more_desc": "Jumbo",
"seq": "4"
,
"257258":
"count": "257258",
"more_desc": "large",
"seq": "1"
,
"name": "some other name",
"description": "this is some other product"
]
我的问题标题“动态键”可能是错误的,但我目前不知道这个问题的更好名称是什么。
任何帮助将不胜感激!
【问题讨论】:
我认为你应该在执行之前将对象的值放在 question_mark 中。你有吗? 嗯,没有。我不知道如何访问问号内的值。为此,我必须做 jsonObj.optJSONObject("141");其中 141 是动态的,我不会提前知道。 【参考方案1】:使用JSONObject keys()获取key,然后迭代每个key得到动态值。
代码大致如下:
// searchResult refers to the current element in the array "search_result" but whats searchResult?
JSONObject questionMark = searchResult.getJSONObject("question_mark");
Iterator keys = questionMark.keys();
while(keys.hasNext())
// loop to get the dynamic key
String currentDynamicKey = (String)keys.next();
// get the value of the dynamic key
JSONObject currentDynamicValue = questionMark.getJSONObject(currentDynamicKey);
// do something here with the value...
【讨论】:
+1 太棒了!那工作得很好!我看到您之前的回复建议使用 keys() 并且我最终打印了外部键。如果不是您的示例代码,我最终会问另一个问题! :P 再次感谢您的及时回复!高时间 SO 支持多次投票以获得很好的答案! 很高兴能够提供帮助 :) 如果您有任何问题,请告诉我。我们(SO 社区)都在这里提供帮助 我用过你的代码一次,又在这里为另一个荣誉 momo 它给我增加了解析动态键数组的新知识,节省了我的时间谢谢 嗨 momo..感谢您的回答。但是我无法使用上述解决方案,因为我正在使用改造并通过在线工具生成器创建 POJO 类,该生成器生成动态值的类。这是没用的。您能否建议我如何为我的问题提供最佳解决方案?【参考方案2】:另一种可能是使用Gson(注意,我这里使用lombok来生成getter/setter、toString等):
package so7304002;
import java.util.List;
import java.util.Map;
import lombok.AccessLevel;
import lombok.Data;
import lombok.NoArgsConstructor;
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
import com.google.gson.reflect.TypeToken;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class JsonDemo
@Data
private static class MyMap
private int count;
@SerializedName("more_description")
private String moreDescription;
private int seq;
@Data
private static class Product
private String product;
private int id;
@SerializedName("question_mark")
private Map<String, MyMap> questionMark;
@Data
private static class MyObject
private String status;
@SerializedName("search_result")
private List<Product> searchResult;
private static final String INPUT = ""; // your JSON
public static void main(final String[] arg)
final MyObject fromJson = new Gson().fromJson(INPUT,
new TypeToken<MyObject>().getType());
final List<Product> searchResult = fromJson.getSearchResult();
for (final Product p : searchResult)
System.out.println("product: " + p.getProduct()
+ "\n" + p.getQuestionMark()+ "\n");
输出:
product: abc
141=JsonDemo.MyMap(count=141, moreDescription=this is abc, seq=2),
8911=JsonDemo.MyMap(count=8911, moreDescription=null, seq=1)
product: XYZ
379=JsonDemo.MyMap(count=379, moreDescription=null, seq=5),
845=JsonDemo.MyMap(count=845, moreDescription=null, seq=6),
12383=JsonDemo.MyMap(count=12383, moreDescription=null, seq=4),
257258=JsonDemo.MyMap(count=257258, moreDescription=null, seq=1)
【讨论】:
感谢您提供有关 GSON、RC 的有用信息和教程。 +1 为创建一个完整的代码示例付出了额外的努力——它也会对这里的其他人有所帮助。 你如何从改造响应中调用它,而 new Gson().fromJson 对我不起作用【参考方案3】:Google Gson使用示例
来自问题的 JSON 数据:
"status": "OK",
"search_result": [
"product": "abc",
"id": "1132",
"question_mark":
"141":
"count": "141",
"more_description": "this is abc",
"seq": "2"
,
"8911":
"count": "8911",
"more_desc": "this is cup",
"seq": "1"
,
"name": "some name",
"description": "This is some product"
,
"product": "XYZ",
"id": "1129",
"question_mark":
"379":
"count": "379",
"more_desc": "this is xyz",
"seq": "5"
,
"845":
"count": "845",
"more_desc": "this is table",
"seq": "6"
,
"12383":
"count": "12383",
"more_desc": "Jumbo",
"seq": "4"
,
"257258":
"count": "257258",
"more_desc": "large",
"seq": "1"
,
"name": "some other name",
"description": "this is some other product"
]
示例代码:
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
public class GsonExercise
public static void main(String[] args)
String jsonString = "\"status\":\"OK\",\"search_result\":[\"product\":\"abc\",\"id\":\"1132\",\"question_mark\":\"141\":\"count\":\"141\",\"more_description\":\"this is abc\",\"seq\":\"2\",\"8911\":\"count\":\"8911\",\"more_desc\":\"this is cup\",\"seq\":\"1\",\"name\":\"some name\",\"description\":\"This is some product\",\"product\":\"XYZ\",\"id\":\"1129\",\"question_mark\":\"379\":\"count\":\"379\",\"more_desc\":\"this is xyz\",\"seq\":\"5\",\"845\":\"count\":\"845\",\"more_desc\":\"this is table\",\"seq\":\"6\",\"12383\":\"count\":\"12383\",\"more_desc\":\"Jumbo\",\"seq\":\"4\",\"257258\":\"count\":\"257258\",\"more_desc\":\"large\",\"seq\":\"1\",\"name\":\"some other name\",\"description\":\"this is some other product\"]";
JsonObject jobj = new Gson().fromJson(jsonString, JsonObject.class);
JsonArray ja = jobj.get("search_result").getAsJsonArray();
ja.forEach(el ->
System.out.println("product: " + el.getAsJsonObject().get("product").getAsString());
JsonObject jo = el.getAsJsonObject().get("question_mark").getAsJsonObject();
jo.entrySet().stream().forEach(qm ->
String key = qm.getKey();
JsonElement je = qm.getValue();
System.out.println("key: " + key);
JsonObject o = je.getAsJsonObject();
o.entrySet().stream().forEach(prop ->
System.out.println("\tname: " + prop.getKey() + " (value: " + prop.getValue().getAsString() + ")");
);
);
System.out.println("");
);
输出:
product: abc
key: 141
name: count (value: 141)
name: more_description (value: this is abc)
name: seq (value: 2)
key: 8911
name: count (value: 8911)
name: more_desc (value: this is cup)
name: seq (value: 1)
product: XYZ
key: 379
name: count (value: 379)
name: more_desc (value: this is xyz)
name: seq (value: 5)
key: 845
name: count (value: 845)
name: more_desc (value: this is table)
name: seq (value: 6)
key: 12383
name: count (value: 12383)
name: more_desc (value: Jumbo)
name: seq (value: 4)
key: 257258
name: count (value: 257258)
name: more_desc (value: large)
name: seq (value: 1)
【讨论】:
如果响应中包含数组和jsonobjects,则上述所有答案都有效,如果响应不是json数组,而是已在此线程中发布的相同类型的响应,如何获取问号里面的值,类似的问题贴在这里,请指导。 ***.com/questions/63639243/…【参考方案4】:同样的事情也可以使用 GSON 来完成,但不是使用 GSON 转换器适配器来转换成 POJO。我们将手动解析它。这为我们提供了动态 JSON 数据的灵活性。 假设在我的情况下,JSON 格式如下所示。
"dateWiseContent":
"02-04-2017": [
"locality": " Cross Madian Cross Rd No 4"
],
"04-04-2017": [
"locality": "Dsilva Wadi"
,
"locality": " Cross Madian Cross Rd No 4",
"appointments": []
]
在这种情况下,dateWiseContent 具有 动态对象键 所以我们将使用 JsonParser 类解析这个 json 字符串。
//parsing string response to json object
JsonObject jsonObject = (JsonObject) new JsonParser().parse(resource);
//getting root object
JsonObject dateWiseContent = jsonObject.get("dateWiseContent").getAsJsonObject();
使用Map.Entry<String, JsonElement>
获取动态密钥,如下所示
// your code goes here
for (Map.Entry<String, JsonElement> entry : dateWiseContent.entrySet())
//this gets the dynamic keys
String dateKey = entry.getKey();
//you can get any thing now json element,array,object according to json.
JsonArray jsonArrayDates = entry.getValue().getAsJsonArray();
int appointmentsSize = jsonArrayDates.size();
for (int count = 0; count < appointmentsSize; count++)
JsonObject objectData = jsonArrayDates.get(count).getAsJsonObject();
String locality = objectData.get("locality").getAsString();
类似地,任何级别的动态 json 都可以使用 Map.Entry<String,JsonElement>
进行解析
【讨论】:
【参考方案5】:你可以使用这个逻辑。使用 org.json 库
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20211205</version>
</dependency>
public void parseJson(JSONObject jo, String key)
Iterator<?> keyIterator;
String key1;
if (jo.has(key))
System.out.println(jo.get(key));
else
keyIterator = jo.keys();
while (keyIterator.hasNext())
key1 = (String) keyIterator.next();
if (jo.get(key1) instanceof JSONObject)
if (!jo.has(key))
parseJson(jo.getJSONObject(key1), key);
else if (jo.get(key1) instanceof JSONArray)
JSONArray jsonarray = jo.getJSONArray(key1);
Iterator<?> itr = jsonarray.iterator();
while (itr.hasNext())
String arrayString = itr.next().toString();
JSONObject jo1 = new JSONObject(arrayString);
if (!jo1.has(key))
parseJson(jo1, key);
【讨论】:
您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。以上是关于如何解析嵌套 JSON 结果中的动态 JSON 键?的主要内容,如果未能解决你的问题,请参考以下文章
如何在没有外部递归函数的情况下解析多个嵌套的 JSON 键?
如何在几个键相等的情况下使用 Python 正确解析嵌套的 json
如何使用json方法解析android中没有键名的数组内的嵌套json编码数组?