我正在使用 Gson 来解析和写入 JSON 数据。
[{
"Source":"IN",
"Type":"PRD",
"Name":"ABC"
"IsActive":true
}, {
"Source":"IN",
"Type":"COB",
"Name":"XYZ"
"IsActive":true
}, {
"Source":"PRo",
"Type":"RPT",
"Name":"TEST"
"IsActive":true
}]
Run Code Online (Sandbox Code Playgroud)
如何根据某些属性值获取 JSON 节点?例如,我想获得一个值为Source= PRo、Type=RPT和Name=的节点TEST。
我怎样才能用 Gson 做到这一点?
Lyu*_*riv 13
正如我上面所说,Gson 不是一个查询库。但是这里至少有四种策略可以与 Gson 一起使用:
以上每一种都有其自身的优点和缺点。对特定节点应用一些修改是一个微不足道的 filter-and-then-forEach 问题,并且可以通过命令式for/if或使用 Java 8 Stream API轻松解决。
JSON 树模型用于在内存中构建特定 JSON 文档的 JSON 表示。拥有类似 DOM 的结构,您可以轻松地遍历和修改任何树叶。但是,它需要大量内存。
try ( final Reader reader = getPackageResourceReader(Q43200432.class, "q43200432.json") ) {
final JsonArray rows = jsonParser.parse(reader).getAsJsonArray();
StreamSupport.stream(rows.spliterator(), false)
.map(JsonElement::getAsJsonObject)
.filter(jsonObject -> jsonObject.get("Source").getAsString().equals("PRo")
&& jsonObject.get("Type").getAsString().equals("RPT")
&& jsonObject.get("Name").getAsString().equals("TEST")
)
.forEach(jsonObject -> jsonObject.add("IsActive", new JsonPrimitive(false)));
System.out.println(rows);
}
Run Code Online (Sandbox Code Playgroud)
与上面类似,但行结构甚至不与 Gson JSON 树模型 API 绑定,因此值可以是字面上的任何类型。
private static final Gson gson = new Gson();
private static final Type rowListType = new TypeToken<List<Map<String, Object>>>() {
}.getType();
...
try ( final Reader reader = getPackageResourceReader(Q43200432.class, "q43200432.json") ) {
final List<Map<String, Object>> rows = gson.fromJson(reader, rowListType);
rows.stream()
.filter(r -> r.get("Source").equals("PRo")
&& r.get("Type").equals("RPT")
&& r.get("Name").equals("TEST"))
.forEach(r -> r.put("IsActive", false));
System.out.println(gson.toJson(rows, rowListType));
}
Run Code Online (Sandbox Code Playgroud)
final class Row {
@SerializedName("Source")
String source;
@SerializedName("Type")
String type;
@SerializedName("Name")
String name;
@SerializedName("IsActive")
boolean isActive;
}
Run Code Online (Sandbox Code Playgroud)
private static final Gson gson = new Gson();
private static final Type rowListType = new TypeToken<List<Row>>() {
}.getType();
...
try ( final Reader reader = getPackageResourceReader(Q43200432.class, "q43200432.json") ) {
final List<Row> rows = gson.fromJson(reader, rowListType);
rows.stream()
.filter(r -> "PRo".equals(r.source) && "RPT".equals(r.type) && "TEST".equals(r.name))
.forEach(r -> r.isActive = false);
System.out.println(gson.toJson(rows, rowListType));
}
Run Code Online (Sandbox Code Playgroud)
流允许通过令牌读取 JSON 令牌并进行某种分析。由于流不需要将整个文档存储在内存中,因此它甚至可以处理无限流,但是它看起来可能有点难以使用。
private static final Gson gson = new Gson();
...
final TypeAdapter<JsonObject> jsonObjectTypeAdapter = gson.getAdapter(JsonObject.class);
final Writer writer = new StringWriter();
try ( final JsonReader jsonReader = new JsonReader(getPackageResourceReader(Q43200432.class, "q43200432.json"));
final JsonWriter jsonWriter = new JsonWriter(writer) ) {
jsonReader.beginArray();
jsonWriter.beginArray();
while ( jsonReader.hasNext() ) {
final JsonObject jsonObject = jsonObjectTypeAdapter.read(jsonReader);
if ( jsonObject.get("Source").getAsString().equals("PRo")
&& jsonObject.get("Type").getAsString().equals("RPT")
&& jsonObject.get("Name").getAsString().equals("TEST") ) {
jsonObject.add("IsActive", new JsonPrimitive(false));
}
jsonObjectTypeAdapter.write(jsonWriter, jsonObject);
}
jsonReader.endArray();
jsonWriter.endArray();
}
System.out.println(writer);
Run Code Online (Sandbox Code Playgroud)
以上四种策略都会产生以下输出:
[{"Source":"IN","Type":"PRD","Name":"ABC","IsActive":true},{"Source":"IN","Type":"COB", "Name":"XYZ","IsActive":true},{"Source":"PRo","Type":"RPT","Name":"TEST","IsActive":false}]
请注意,位于 的最后一个元素$[2].IsActive设置为false。
| 归档时间: |
|
| 查看次数: |
3788 次 |
| 最近记录: |