Compare two JSON and also show activity which column we changed? - java

How can I compare two JSON, one I get from the database and the second One from FrontEnd(means when I click on the edit button)? How can I compare these two JSON?
First Json
{
"id": 2,
"createdAt": "07-01-2021 15:26:16",
"updatedAt": "07-01-2021 15:26:16",
"offerAcceptedDate": "06-30-2021 07:14:00",
"offerAmount": 100000,
"offerDate": "06-30-2021 07:14:00",
"offerFile": "string",
"possibleCloseDate": "06-30-2021 07:14:00",
"remarks": "string",
"salesId": 8,
"status": "Active",
"contactId": 32,
"createdById": 1,
"offerAcceptedById": 1
}
2nd JSON
{
"createdAt": "09-01-2021 15:26:16",
"updatedAt": "10-01-2021 15:26:16",
"offerAcceptedDate": "06-30-2021 07:14:00",
"offerAmount": 500000,
"offerDate": "06-30-2021 07:14:00",
"offerFile": "string",
"possibleCloseDate": "06-30-2021 07:14:00",
"remarks": "string",
"salesId": 8,
"status": "Active",
"contactId": 32,
"createdById": 1,
"offerAcceptedById": 1
}
Also, compare these two JSON and also show activity what column" changed.
Like this:
createdAt: Changed
updatedAt: Changed
offeramount: Changed

1)First of all I get data from DB using findById(JPA Repository)
2)Compare Db field and request body field
like that :
LeadOffer leadOffer = leadOfferRepository.findById(offerId).orElse(null);
JsonObject jsonObject = new JsonObject();
JsonArray jsonArray= new JsonArray();
if (leadOffer.getAmount() != leadOfferRequest.getAmount())
{
offer.setAmount(leadOfferRequest.getAmount());
jsonObject.addProperty("amount",leadOfferRequest.getAmount() );
jsonObject1.addProperty("amount",leadOffer.getAmount() );
}
jsonArray.add(jsonObject);

You can use guava library for this purpose. For example :
String json1 = "{\"name\":\"ABC\", \"city\":\"XYZ\", \"state\":\"CA\"}";
String json2 = "{\"city\":\"XYZ\", \"street\":\"123 anyplace\", \"name\":\"ABC\"}";
Gson g = new Gson();
Type mapType = new TypeToken<Map<String, Object>>(){}.getType();
Map<String, Object> firstMap = g.fromJson(json1, mapType);
Map<String, Object> secondMap = g.fromJson(json2, mapType);
System.out.println(Maps.difference(firstMap, secondMap).entriesDiffering());
This shows the keys that are present in both the maps but have different values

Related

Generic Json Map Setter in Java

Suppose I have an empty Map<String, Object> map or a Map<String, Object> map with some fields added.
In this case, I want to create a generic java method that I can set to the map I have using the values such as map, path, value type and value object that I will give as input.
The method outline I intend to create can be seen below.
public void genericJsonMapSet(Map<String, Object> jsonMap, String setPath, String setValueType, Object setValue) {
//Set JsonMap code
}
The json representation of the map before and after the following calls of the method to be created should be as follows.
genericJsonMapSet(jsonMap, "setid()", "string", "a9a9940d-593f-4546-8065-6d70370d9f64");
genericJsonMapSet(jsonMap, "setrequestDate()", "string", "2022-10-10 16:20:15");
genericJsonMapSet(jsonMap, "setuserCharacteristic[1].setvalueType()", "string", "string");
genericJsonMapSet(jsonMap, "setuserCharacteristic[1].setname()", "string", "username");
genericJsonMapSet(jsonMap, "setuserCharacteristic[1].setvalue()", "string", "taner.turan");
genericJsonMapSet(jsonMap, "setuserCharacteristic[2].setvalueType()", "string", "integer");
genericJsonMapSet(jsonMap, "setuserCharacteristic[2].setname()", "string", "id");
genericJsonMapSet(jsonMap, "setuserCharacteristic[2].setvalue()", "integer", "23");
Before:
{
}
After:
{
"id": "a9a9940d-593f-4546-8065-6d70370d9f64",
"requestDate": "2022-10-10 16:20:15",
"userCharacteristic": [
{
"valueType": "string",
"name": "username",
"value": "taner.turan"
},
{
"valueType": "integer",
"name": "id",
"value": 23
}
]
}
Can anyone provide code for this?
This project works similarly. I wrote it.. a long long time ago, as far as I know nobody uses it. Map<String, Object> is not java-like at all; there is almost no purpose to such a thing. I encapsulated the notion into a JSON object instead. Also, you don't use strings to 'set' things, again, un-java like. Thus, this code:
Map<String, Object> jsonMap = new HashMap<>();
genericJsonMapSet(jsonMap, "setid()", "string", "a9a9940d-593f-4546-8065-6d70370d9f64");
genericJsonMapSet(jsonMap, "setuserCharacteristic[1].setvalueType()", "string", "string");
genericJsonMapSet(jsonMap, "setuserCharacteristic[2].setvalue()", "integer", "23");
Becomes:
JSON j = JSON.newMap();
j.get("setId").setString("a9a9940d-593f-4546-8065-6d70370d9f64");
j.get("setuserCharacteristic").add().setString("string");
j.get("setuserCharacteristic").get(2).setInteger(23);
add() is the same as .get(i) where i is one larger than whatever is there already. You can get non-existent things; they are created automatically once you .set anywhere in the 'chain'. i.e.:
JSON j = JSON.newMap();
j.get("foo").get("bar").setString("hello");
Gives you JSON structure:
{
"foo": {
"bar": "hello"
}
}
Link to code on github
You can make use of the function unflatten() of library Josson to do what you want.
https://github.com/octomix/josson
Josson josson = Josson.create();
josson.put("id", "a9a9940d-593f-4546-8065-6d70370d9f64");
josson.put("requestDate", "2022-10-10 16:20:15");
josson.put("userCharacteristic[1].valueType", "string");
josson.put("userCharacteristic[1].name", "username");
josson.put("userCharacteristic[1].value", "taner.turan");
josson.put("userCharacteristic[2].valueType", "integer");
josson.put("userCharacteristic[2].name", "id");
josson.put("userCharacteristic[2].value", 23);
JsonNode node = josson.getNode("unflatten('.[]')");
System.out.println(node.toPrettyString());
Output
{
"id" : "a9a9940d-593f-4546-8065-6d70370d9f64",
"requestDate" : "2022-10-10 16:20:15",
"userCharacteristic" : [ {
"valueType" : "string",
"name" : "username",
"value" : "taner.turan"
}, {
"valueType" : "integer",
"name" : "id",
"value" : 23
} ]
}

Trying to get a child key value from a json object saved in an map-variable in sketchware

i have the following json as a get response:
{
"global": {
"name": "Lz Cha0S",
"uid": xxx,
"platform": "X1",
"level": 521,
"toNextLevelPercent": 31,
"internalUpdateCount": 22822,
"bans": {
"isActive": false,
"remainingSeconds": 0,
"last_banReason": "COMPETITIVE_DODGE_COOLDOWN"
},
"rank": {
"rankScore": 4227,
"rankName": "Gold",
"rankDiv": 2,
"rankImg": "https:\/\/api.apexlegendsstatus.com\/assets\/ranks\/gold2.png"
},
"battlepass": {
"level": "-1"
}
},
"realtime": {
"lobbyState": "open",
"isOnline": 0,
"isInGame": 0,
"canJoin": 0,
"partyFull": 0,
"selectedLegend": "Bloodhound"
},
"legends": {
"selected": {
"LegendName": "Bloodhound",
"data": [
{
"name": "Kills",
"value": 331,
"key": "kills"
},
{
"name": "Beast of the hunt kills",
"value": 62,
"key": "beast_of_the_hunt_kills"
},
{
"name": "Season 4 Wins",
"value": 20,
"key": "wins_season_4"
}
],
"ImgAssets": {
"icon": "http:\/\/api.apexlegendsstatus.com\/assets\/icons\/bloodhound.png",
"banner": "http:\/\/api.apexlegendsstatus.com\/assets\/banners\/bloodhound.jpg"
}
},
"all": {cutted becouse off to much Text...},
"mozambiquehere_internal": {
"isNewToDB": false,
"claimedBy": "-1",
"APIAccessType": "BASIC",
"ClusterID": "2",
"rate_limit": {
"max_per_second": 3,
"current_req": "1"
}
},
"total": {
"kills": {
"name": "Kills",
"value": 331
},
"beast_of_the_hunt_kills": {
"name": "Beast of the hunt kills",
"value": 62
},
"wins_season_4": {
"name": "Season 4 Wins",
"value": 20
},
"kd": {
"value": -1,
"name": "KD"
}
}
}
I saved this json to a map with the skecthware block
Json [response] to Map [response]json to map block
Now a want to get the name key with is in the global key, but if i use the block
Map [response] get key [name]
Map get key name
It gives a error that name cannot be found (null exeption)
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.Object.toString()' on a null object reference at com.chaos droid.attack.MainActivity$3.onResponse(MainActivity.java:365) se(MainActivity.java:365) at com.chaosdroid.attack.RequestNetwork er$3$2.run(RequestNetworkController.java:171) at android.os.Handler.handleCallback(Handler.java:
873) at
android.os.Handler.dispatchMessage(Handler.ja va:99) at android.os.Looper.loop(Looper.java:193) at android.app.Activity Thread.main(ActivityThread.j ava:6718) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:491) ArgsCaller.run(RuntimeInit.java:491)
at com.android.internal.os.ZygoteInit.main(Zygotel nit.java:858)
END APPLICATION
If i use the global key in the get key block it returns the global key as Text
Map [response] get key [global]
get map key global
returns
{name=Lz Cha0S, uid=xxx, platform=X1, level=521.0, toNextLevelPercent=31.0, internalUpdateCount=22822.0, bans={isActive=false, remainingSeconds=0.0, last_banReason=COMPETITIVE_DODGE_COOLDOWN}, rank={rankScore=4227.0, rankName=Gold, rankDiv=2.0, rankImg=https://api.apexlegendsstatus.com/assets/ranks/gold2.png}, battlepass={level=-1}}
i tried to save that output to a New map variable but its not a valid json objet so the json to map block is not working.
It looks like the map value can store only one key with value not a child key. When i get the response where i have an error in the get field it returns an error json that looks like this:
{"Error": "Player not found. Try again?"}
Here can i get the key succsessful with the same get key block:
Map [response] get key [global]
Get map.key error
i also tried to parse the json with Java in an add source directly block with:
JSONObject jObject = new JSONObject(result);
String aJsonString = jObject.getString("name");
But then i get a sketchware Compiler error that jsonobjet cannot be resolved to a type
1. ERROR in /storage/emulated/0/.sketchware/mysc/717/app/src/main/ java/com/chaosdroid/atrack/MainActivity.java (at line 355) String result = response;
Type mismatch: cannot convert from HashMap<String,Object> to String
2. ERROR in /storage/emulated/0/.sketchware/mysc/717/app/src/main/ java/com/chaos droid/attack/MainActivity.java (at line 357) JSONObject jObject = new JSONObject(result);
JSONObject cannot be resolved to a type
3. ERROR in /storage/emulated/0/.sketchware/mysc/717/app/src/main/ java/com/chaosdroid/atrack/MainActivity.java (at line 357) JSONObject Object = new JSONObject(result);
JSONObject cannot be resolved to a type
3 problems (3 errors)
And i dont know how to import jsonobject into sketchware.
How can a get the child key of global from this json?
Edit: (thanks to #Dmytro Kyrychkov)
For sketchware users: you need the full declaration of the function you want to use because you cant import
libraries in sketchware. For this example this will working in an add source directly block in sketchware:
String jsonStr = strResponse;
Gson gson = new Gson();
HashMap<String, Object> json = gson.fromJson(jsonStr, HashMap.class);
com.google.gson.internal.LinkedTreeMap<String, Object> global = (com.google.gson.internal.LinkedTreeMap<String, Object>) json.get("global");
String name = (String) global.get("name");
If you want to get a JSON object child field you should follow its structure during parsing:
public static void main(String... args) throws IOException {
String jsonStr = new String(Files.readAllBytes(PATH_TO_JSON));
Gson gson = new Gson();
HashMap<String, Object> json = gson.fromJson(jsonStr, HashMap.class);
LinkedTreeMap<String, Object> global = (LinkedTreeMap<String, Object>) json.get("global");
String name = (String) global.get("name");
System.out.println(name);
}
Output:
Lz Cha0S
Process finished with exit code 0
I hope it helps you :)
Create two map variables, map1 and map2
now get your response in map1
and then use Json[map:[map1]get kay "global"] to map:[map2]],
Now you have your JSON data ready to use with ListMap, remember that your JSON data is now inside map2, so whenever you want to use it remember to get it from map2.

Itterate through List of objects recieved in JSON

I have the following JSON data:
[
{
"id": 4,
"siteName": "site1",
"addressLine1": "address1",
"addressLine2": "address2",
"town": "town1",
"postcode": "postcode1",
"contactName": "name1",
"contactNumber": "number1",
"contactEmail": "email1"
},
{
"id": 5,
"siteName": "site2",
"addressLine1": "address1",
"addressLine2": "address2",
"town": "town1",
"postcode": "postcode1",
"contactName": "name1",
"contactNumber": "number1",
"contactEmail": "email1"
},
]
I'm parsing the data but it simply outputs one long string. I'd like to access each element within each object.
UPDATE: I'm outputting the individual elements, but for some reason the 'id' property is considered a double?
Map<String,Object> jsonArr = new JSONParser().parseJSON(new InputStreamReader(new ByteArrayInputStream(r.getResponseData()), "UTF-8"));
java.util.List<Map<String, Object>> content = (java.util.List<Map<String, Object>>)jsonArr.get("root");
for(Map<String, Object> obj : content) {
Log.p((int)obj.get("id"));
Log.p((String)obj.get("siteName"));
Log.p((String)obj.get("addressLine1"));
Log.p((String)obj.get("addressLine2"));
Log.p((String)obj.get("town"));
Log.p((String)obj.get("postcode"));
Log.p((String)obj.get("contactName"));
Log.p((String)obj.get("contactNumber"));
Log.p((String)obj.get("contactEmail"));
}
As you're using Codename One, parseJSON always returns a Map<String, Object>, but behaves differently when the root element is an array. In that case, the returned Map contains an object whose key is "root" which you then can iterate on to obtain the actual objects.
Map<String, Object> data = json.parseJSON(new InputStreamReader(
new ByteArrayInputStream(r.getResponseData()), "UTF-8"));
List<Map<String, Object>> content = (java.util.List<Map<String, Object>>)data.get("root");
for(Map<String, Object> obj : content) {
Log.p(obj.getValue().toString());
}
For further info see the documentation for the parseJSON method.
You are getting an array of objects as it stats with [ and ends with ]. You have to try like this.
JSONArray jsonArr = new JSONParser().parseJSON(new InputStreamReader(new ByteArrayInputStream(r.getResponseData()), "UTF-8"));
for (int i = 0; i < jsonArr.length(); i++) {
String siteName = jsonArr.getJSONObject(i).getString("siteName");
System.out.println(siteName);
}

Get Value from JSON into Map, then value out of the Map

I have the following JSON data:
JSON:
[{
"valInternalCode": "NE",
"valMinimumInputString": "NE",
"valExternalRepresentation": "Northeast",
"valActionCode1": "1",
"valActionCode2": null,
"valActionCode3": null,
"valActionCode4": null,
"id": {
"valcodeId": "X.LOCATION",
"pos": 1
},
"uniqueId": "X.LOCATION-1",
"caption": "Northeast"
}, {
"valInternalCode": "NW",
"valMinimumInputString": "NW",
"valExternalRepresentation": "Northwest",
"valActionCode1": "1",
"valActionCode2": null,
"valActionCode3": null,
"valActionCode4": null,
"id": {
"valcodeId": "X.LOCATION",
"pos": 2
},
"uniqueId": "X.LOCATION-2",
"caption": "Northwest"
}
I am able to parse it and create a Map from the data like so:
Gson gson = new Gson();
Type collectionType = new TypeToken<Collection<Map>>(){}.getType();
Collection<Map> dataCollection = gson.fromJson(jsonString.toString(), collectionType);
I can then iterate through it and get a value that I need using the Key like so:
iterator.next().get("valInternalCode");
What I am struggling with is how to get something that is inside of the id field:
"id": {
"valcodeId": "X.LOCATION",
"pos": 2
},
I am using Hibernate to get the data from a non normalized Oracle database (that is why hibernate creates the id field the way it does)
EDIT:
My attempt at an ugly way of doing it. Basically looping within the loop:
while (valIterator.hasNext()) {
Map currentVal = valIterator.next();
String valId = "";
Collection<Map> idVal = (Collection<Map>) currentVal.get("id");
Iterator<Map> valIdIterator = idVal.iterator();
while (valIdIterator.hasNext()) {
Map valIdCurrentVal = valIdIterator.next();
valId = valIdCurrentVal.get("valcodeId").toString();
}
}
Getting a ClassCastException when I try to cast currentVal.get("id") to a Collection

How to parse JSONObject with other JSONObjects inside it?

I have a question about getting jsonobjects out of a jsonobject.
This is what im getting back:
{
"data": {
"someid": {
"air_by_date": 0,
"cache": {
"banner": 1,
"poster": 1
},
"language": "en",
"network": "somenetwork",
"next_ep_airdate": "somedate",
"paused": 0,
"quality": "somequality",
"show_name": "somename",
"status": "Continuing",
"tvdbid": someid,
"tvrage_id": someid,
"tvrage_name": "Showname"
},
"someid": {
"air_by_date": 0,
"cache": {
"banner": 1,
"poster": 1
},
"language": "en",
"network": "somenetwork",
"next_ep_airdate": "",
"paused": 0,
"quality": "somequality",
"show_name": "somename",
"status": "Continuing",
"tvdbid": someid,
"tvrage_id": someid,
"tvrage_name": "somename"
},
But how am i supposed to create "ShowObjects" of them. I know how it works with JSONArrays but i have never done this kind of JSON before.
This is what i got untill now:
String json = download(url);
JSONObject result = new JSONObject(json);
JSONObject resultData = result.getJSONObject("data");
Copied from this answer:
Use the keys() iterator to iterate over all the properties, and call get() for each.
Iterator<String> iter = json.keys();
while (iter.hasNext()) {
String key = iter.next();
try {
Object value = json.get(key);
} catch (JSONException e) {
// Something went wrong!
}
}
Try using Jackson or Gson for these tasks.
With Jackson you would do something like this:
class Response() {
public String message;
public String result;
public Map<String, Object> data;
}
ObjectMapper mapper = new ObjectMapper()
Resonse respone = mapper.readValue(json, Response.class)
or use a custom deserializer to read those values out.
I will give you an example how to fetch the objects and vars in your "data" json:
lets say the second "someid" is : "123". We will fetch the second jsonObject now :
JSONObject secondJsonSomeId = resultData.getJsonObject("123");
Now we will fetch the "banner" ( int =1 ) of the jsonObject named "cache" located in our secondJsonSomeId :
int bannerInsecondJsonSomeId = secondJsonSomeId.getJsonObject("cache").getInt("banner");// bannerInsecondJsonSomeId == 1
the code is not compiled so there might be errors , ask if you have additional questions.

Categories

Resources