I am using Gson to parse and write JSON data.
[{
"Source":"IN",
"Type":"PRD",
"Name":"ABC"
"IsActive":true
}, {
"Source":"IN",
"Type":"COB",
"Name":"XYZ"
"IsActive":true
}, {
"Source":"PRo",
"Type":"RPT",
"Name":"TEST"
"IsActive":true
}]
How can I get the JSON node based on some attribute values? For example, I wanted to get a node whose values are Source
=PRo
, Type
=RPT
and Name
=TEST
.
How can i do it with Gson?
As I said above, Gson is not a querying library. But there are at least four strategies you can use with Gson here:
Each of the above has its own advantages and disadvantages. Applying some modifications to particular nodes is a trivial filter-and-then-forEach problem, and can be solved very easy either with imperative for
/if
or using Java 8 Stream API.
JSON tree models are used to build a JSON representation of a particular JSON document in memory. Having a DOM-like structure, you can traverse and modify any tree leaf easily. However, it requires a lot of memory.
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);
}
Similar to the above, but the rows structure is not even bound with Gson JSON tree model API, thus values can be of any types literally.
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 allows to read JSON token by token and make some kind of analysis. Since streaming does not require the whole document to be stored in memory, it can even process infinite streams, however it may look a bit harder to use.
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);
All four strategies above produce the following output:
[{"Source":"IN","Type":"PRD","Name":"ABC","IsActive":true},{"Source":"IN","Type":"COB","Name":"XYZ","IsActive":true},{"Source":"PRo","Type":"RPT","Name":"TEST","IsActive":false}]
Note that the last element located at $[2].IsActive
is set to false
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With