我正在使用Gson来解析和编写JSON数据。
namespace inet {
Define_Module(PC);
void PC::initialize() {
TCPSocket mysocket;
// ...
}
}
如何根据某些属性值获取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
}]
= Source
,PRo
= Type
和RPT
= Name
的节点。
我怎么能用Gson做到这一点?
答案 0 :(得分:3)
正如我上面所说,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);
}
与上面类似,但行结构甚至不与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));
}
final class Row {
@SerializedName("Source")
String source;
@SerializedName("Type")
String type;
@SerializedName("Name")
String name;
@SerializedName("IsActive")
boolean isActive;
}
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));
}
Streaming允许通过令牌读取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);
上述所有四种策略都会产生以下输出:
[{ “源”: “IN”, “类型”: “PRD”, “名称”: “ABC”, “IsActive”:真},{ “源”: “IN”, “类型”:” COB”, “姓名”: “XYZ”, “IsActive”:真正},{ “源”: “亲”, “类型”: “RPT”, “姓名”: “TEST”, “IsActive”:假}]
请注意,位于$[2].IsActive
的最后一个元素设置为false
。