I am a very beginner about JSON...
How can I get the value of "3037904" from the following JSON Object in Java program?
{"query":{"pages":{"3037904":{"pageid":3037904,"ns":0,"title":"Kempinski",
"categories":[{"ns":14,"title":"Category:Companies established in 1897"},{"ns":14,"title":"Category:Hotel chains"},{"ns":14,"title":"Category:Kempinski Hotels"}]}}}}
I tried to
JSONObject query = json.getJSONObject("query");
int pages = query.getInt("pages");
But it takes
"{"3037904":{"pageid":3037904,"ns":0,"title":"Kempinski",
"categories":[{"ns":14,"title":"Category:Companies established in 1897"},{"ns":14,"title":"Category:Hotel chains"},{"ns":14,"title":"Category:Kempinski Hotels"}]}}}}",
not only "3037904".
You'll need to do a little more work with your JSONObject.
In this answer I'll assume that you want to get at that pageid value.
Let's only assume the existence of pageid in the nesting - at a specific level:
// "query" is the top-level object:
JSONObject query = json.getJSONObject("query");
// "pages" is a field of "query"
JSONObject pages = query.getJSONObject("pages");
// these will hold the object with the value that you want, and that value:
JSONObject nestedObject = null;
int pageId = 0;
// these are the property names in the "pages" object:
String[] keys = pages.getNames(pages);
// iterate over the keys in the "pages" object, looks for JSONObjects:
for (int i = 0; i < keys.length; i++)
{
try
{
nestedObject = pages.getJSONObject(keys[i]);
// only consider objects with a "pageid" key, stop at the first one:
if (nestedObject.has("pageid"))
break;
}
catch (JSONException je)
{ ; }
}
if (nestedObject != null)
pageId = nestedObject.getInt("pageid");
Your JSON input seems peculiar in that the first nested object has a pages field, that contains another object. The name in plural, pages, and the nested object - which duplicates the key containing the object as a pageid key within the object - suggests that pages should be an array of multiple such objects.
Take a look at the GSON Library: http://code.google.com/p/google-gson/
Here are good examples: https://sites.google.com/site/gson/gson-user-guide#TOC-Primitives-Examples
Gson gson = new Gson();
Map map = gson.fromJson("{\"query\":{\"pages\":{\"3037904\":{\"pageid\":3037904,\"ns\":0,\"title\":\"Kempinski\", \"categories\":[{\"ns\":14,\"title\":\"Category:Companies established in 1897\"},{\"ns\":14,\"title\":\"Category:Hotel chains\"},{\"ns\":14,\"title\":\"Category:Kempinski Hotels\"}]}}}}", HashMap.class);
Map query = (Map) map.get("query");
Map pages = (Map) query.get("pages");
System.out.println(pages.keySet());
Map page = (Map) pages.get("3037904");
System.out.println(page);
System.out.println(page.get("pageid"));
Related
Iterator searchGetResponseIterator = searchGetResponse.entrySet().iterator();
Object obj = null;
Object dataPicker = null;
while(searchGetResponseIterator.hasNext()) {
Map.Entry searchGetResponseElement = (Map.Entry)searchGetResponseIterator.next();
if(searchGetResponseElement.getKey().equals("seSearch")) {
obj = searchGetResponseElement.getValue();
}
}
want to store the "obj" in map. In obj i have this >>
{"columns":[{"exp":{"$ali":"t2acName"},"ali":"sourceacName"},"**id**":"4c99eedc836adbeefd0e10db76a","**table**":"public.4c99eedc836adbeefd0e10db76a","fieldIds":["0336e7c7-b236-41b7-8ae8-194dcfc49693","369bc4de-b220-41a2-a7be-090c6386aa2e","37926ca2-044f-44f2-a349-0f2e1b61f120","2310dcca-010f-4830-b300-01fb00d2d15e","306554be-92b3-41a3-bb24-b59f4adc8b79","21cdee98-e3b4-4da9-a502-587c0a221413","1f26c177-944f-4378-9e26-8ee0882221cc","13532fa7-8320-4cc1-90fb-aa8fcc3f5f6f","16d3a857-e8d5-4172-87f5-a149187ec409",],"executionQueue":[{"flow":0,"start":1574674632999,"count":0,"rEnd":1574676432999,"status":"done"},{"flow":0,"start":1574620200000,"count":0,"rEnd":1574674632999,"status":"done"}]}
and i want to get id and table from table again.
You know the format of obj
{"**id**":"4c99eedc836adbeefd0e10db76a","**table**":"public.
Looks like there is consistent pattern where id appears, and where table appears in that blob of string / json.
Look at RegEx java tutorial and create one to extract id and table
https://www.baeldung.com/regular-expressions-java
An easier way is to convert the Object string to a map and get your fields.
if(searchGetResponseElement.getKey().equals("seSearch")) {
obj = searchGetResponseElement.getValue();
ObjectMapper objectMapper = new ObjectMapper();
HashMap responseMap = objectMapper.readValue(obj.toString(), HashMap.class);
}
Once you have the responseMap, you can inspect that object and get the required hierarchy from it.
For example: ((Map) ((List) responseMap.get("columns")).get(0)).get("id")
Note: The above example may not accurately represent your response model.
Is it possible to change the name of a Json property without serialization with Gson? For example, given this Json
{
"1": {
...
},
"2": {
...
}
}
could I change the "1" to a "3" without removing its contents. I know that the addProperty method adds a new property, or overwrites an existing property with a new value, but I want to change the name of a property without affecting its value. Also, pasting the existing value as the second argument of addProperty will not suffice.
EDIT: To add more context, I will explain the bigger picture. I have a JSON string that is a couple thousand lines long. I'm writing a program leveraging Gson in order to change the values in that JSON string. I am at a point where I not only want to change the values of properties, but the names of the properties themselves. I have done everything so far without serialization.
Here is a snippet of the Java I wrote:
String file = "\\temp.json";
FileReader reader = new FileReader(file);
JsonStreamParser parser = new JsonStreamParser(reader);
// Parse entire JSON
JsonElement element = parser.next();
// Get root element
JsonObject sites = element.getAsJsonObject();
// Get first child element
JsonObject site1 = sites.getAsJsonObject("1");
JsonObject clust1 = site1.getAsJsonObject("CLUST");
for(int i = 1; i < 12; i++) {
// "Dynamic" variable
String num = Integer.toString(i);
// Get property whose name is a number, has siblings
JsonObject one = custCluster1.getAsJsonObject(num);
one.getAsJsonObject().addProperty("name", "cluster" + i);
JsonObject subOne = one.getAsJsonObject("SUB");
subOne.getAsJsonObject().addProperty("name", "aName" + i);
for(int n = 1; n < 1002; n++) {
// "Dynamic" variable
String inst = Integer.toString(n);
// Get property whose name is a number, has siblings
JsonObject subSub = subOne.getAsJsonObject(inst);
// If the property doesn't exist, then don't execute
if(subSub != null) {
JsonArray subSubArray = subSub.getAsJsonArray("SUBSUB");
subSub.getAsJsonObject().remove("name");
int m = 0;
while(m < subSubArray.size()) {
subSubArray.get(m).getAsJsonObject().remove("SR");
subSubArray.get(m).getAsJsonObject().remove("FI");
subSubArray.get(m).getAsJsonObject().remove("IND");
subSubArray.get(m).getAsJsonObject().addProperty("ST", "1");
subSubArray.get(m).getAsJsonObject().addProperty("ID", "2");
subSubArray.get(m).getAsJsonObject().addProperty("DESCR", "hi");
m++;
}
m = 0;
}
}
}
Thanks to #mmcrae for helping and suggesting this method.
Since I'm already saving the (key, value) pairs in variables, you can remove the property whose name you want to change from the parent, and then add it back with a new name and the content that was already saved.
Like this:
JsonObject sites = element.getAsJsonObject();
JsonObject site1 = sites.getAsJsonObject("1");
JsonObject clust1 = site1.getAsJsonObject("CLUST");
site1.remove("CLUST");
site1.add("NEWCLUST", clust1);
We have a requirement to update the JSON data in middle and need to return the updated JSON data using java. Also it should support any type of JSON data.
ex:
Assume {object:{"color":"red","shape":"Triangle"}} is the JSON data and in this we need to update the shape value to Rectangle and we need to return the updated JSON data as below:
{object:{"color":"red","shape":"Rectangle"}}
For this we need to pass the element path ( which element we need to update) and updateText and JSON Data to the JAVA code.
here is the methodCall:
updateValue("object/shape", "Rectangle", "{object:{"color":"red","shape":"Triangle"}}")
We tried below code using Gson library. But with this code we are able to update the targeted Json element, but the requirement is to return the entire JSON data with the updated value.
So please suggest how do we re-build the JSON data with the updated text.
Below is the code we tried to update the Json Data.
public String updateValue(String keyPath, String updateText, String jsonText) {
String[] keys = keyPath.split("/");
JsonParser jsonParser = new JsonParser();
JsonObject jsonObject = (JsonObject) jsonParser.parse(jsonText);
String result = "";
for(String key : keys)
{
if (jsonObject.get(key) instanceof JsonObject)
{
jsonObject = (JsonObject)jsonObject.get(key);
}
else if(jsonObject.get(key) instanceof JsonArray)
{
JsonArray jsonArray = (JsonArray)jsonObject.get(key);
result = jsonArray.toString();
}
else
{
result = jsonObject.get(key).toString();
}
}
result = result.replace(result, updateText);
return result;
}
The problem lies in the way you do the replacements. When you translate the JsonObject to String, you lose the object, and after replacement, you just have the replaced String. To fix it, you need to operate directly on the object, instead of the String counterpart. Because JsonObject is mutable, holding a reference to the input will reflect the changes. One drawback is you can't replace a value in a JsonArray this way, partly because you don't know which element to replace. To accomplish that, you will need a little more in the input(either the value to replace or the element position).
public String updateValue(String keyPath, String updateText, String jsonText) {
String[] keys = keyPath.split("/");
JsonParser jsonParser = new JsonParser();
JsonObject jsonObject = (JsonObject) jsonParser.parse(jsonText);
JsonObject returnVal = jsonObject; // This holds the ref to target json object
JsonPrimitive jp = new JsonPrimitive(updateText);
String finalKey = keys[keys.length - 1];
for(String key : keys)
{
if (jsonObject.get(key).isJsonObject())
{
jsonObject = (JsonObject)jsonObject.get(key);
}
}
jsonObject.remove(finalKey);
jsonObject.add(finalKey, jp);
return returnVal.toString();
}
You can use JsonPath lib for that and try using the following code.
private static final Configuration configuration = Configuration.builder()
.jsonProvider(new JacksonJsonNodeJsonProvider())
.mappingProvider(new JacksonMappingProvider())
.build();
JsonNode updatedJson = JsonPath.using(configuration).parse(originaljson)
.set("use the path to go for value", "new value").json();
json = updatedJson.toString();
I have a JSON array which contains objects such as this:
{
"bjones": {
"fname": "Betty",
"lname": "Jones",
"password": "ababab",
"level": "manager"
}
}
my User class has a username which would require the JSON object's key to be used. How would I get the key of my JSON object?
What I have now is getting everything and creating a new User object, but leaving the username null. Which is understandable because my JSON object does not contain a key/value pair for "username":"value".
Gson gson = new Gson();
JsonParser p = new JsonParser();
JsonReader file = new JsonReader(new FileReader(this.filename));
JsonObject result = p.parse(file).getAsJsonObject().getAsJsonObject("bjones");
User newUser = gson.fromJson(result, User.class);
// newUser.username = null
// newUser.fname = "Betty"
// newUser.lname = "Jones"
// newUser.password = "ababab"
// newUser.level = "manager"
edit:
I'm trying to insert "bjones" into newUser.username with Gson, sorry for the lack of clarification
Use entrySet to get the keys. Loop through the entries and create a User for every key.
JsonObject result = p.parse(file).getAsJsonObject();
Set<Map.Entry<String, JsonElement>> entrySet = result.entrySet();
for(Map.Entry<String, JsonElement> entry : entrySet) {
User newUser = gson.fromJson(p.getAsJsonObject(entry.getKey()), User.class);
newUser.username = entry.getKey();
//code...
}
Using keySet() directly excludes the necessity in iteration:
ArrayList<String> objectKeys =
new ArrayList<String>(
myJsonObject.keySet());
Your JSON is fairly simple, so even the manual sort of methods (like creating maps of strings etc for type) will work fine.
For complex JSONs(where there are many nested complex objects and lists of other complex objects inside your JSON), you can create POJO for your JSON with some tool like http://www.jsonschema2pojo.org/
And then just :
final Gson gson = new Gson();
final MyJsonModel obj = gson.fromJson(response, MyJsonModel.class);
// Just access your stuff in object. Example
System.out.println(obj.getResponse().getResults().get(0).getId());
In the client side, I have constructed a JSOnARRAY like this:
{"filterEntries":[{"dataName":"mainContact","filterValue":"BILLGATES"}]}.
On the server side (java), I can retireve the values using :
jfilter = JSONValue.parse(jsonFilterStr); //jsonFilterStr={"filterEntries":[{"dataName":"mainContact","filterValue":"BILLGATES"}]}.
JSONArray jFilterEntries = (JSONArray) jfilter.get("filterEntries");
for (int i=0;i<jFilterEntries.size();i++){
JSONObject jFilterEntry = (JSONObject) jFilterEntries.get(i);
String dataName = (String) jFilterEntry.get("dataName");
String filterValue = (String) jFilterEntry.get("filterValue");
}
But the existing app is using flex.json.deserializer and I am unable to achieve the same using flex.json.deserializer. How should I proceed?
I wish to do something like this:
JSONDeserializer jsonDeserializer = new JSONDeserializer();
jsonDeserializer.use(null, List.class);
List<Map<String,String>> lMap= (List<Map<String,String>>)jsonDeserializer.deserialize(params);
Remember the top object that wraps the array. You have to handle that as well. You have to tell it to expect a Map inside the List. To do that you have to specify the type contained in the list by using the path expression "values".
Map<String,List<Map<String,String>>> result = new JSONDeserializer<Map<String,List<Map<String,String>>>>()
.use("values",List.class)
.use("values.values", Map.class)
.deserialize( json);
List<Map<String,String>> filterEntries = result.get("filterEntries");
Updated: Add the new keyword, and made the generic types on the right match the left.