how to deserilize JSON with dynamic numeric field names, using GSON? - java

I have a JSON file in this format:
title 1
{
"0" : 2,
"1" : 5,
"2" : 8
}
title 2
{
"1" : 44,
"2" : 15,
"3" : 73,
"4" : 41
}
As you can see the indexes are dynamic - in title 1 they were: "0","1","2" and for title 2 they are: "1","2","3","4"
I don't know how to read this using GSON.
I need to somehow convert it into a java object so I can go on and process the data.
Any help is most welcome.

First thing is the JSON that is represented on the page is not valid JSON invalid, so my recommendation is based on the fallowing JSON. Just giving you full disclosure.
{
"title 1":{
"0":2,
"1":5,
"2":8
},
"title 2":{
"1":44,
"2":15,
"3":73,
"4":41
}
}
OPTION 1 (not how i would solve this issue)
This would serialize it as a general object that you could loop threw to process.
new Gson().fromJson(yourJsonString,Object.class);
OPTION 2 (best bet in my opinion)
If you had control of how the object cam in i would do something like this
{
"listOfTitles":[
{
"title":[
{
"key":"0",
"value":1234
},
{
"key":"1",
"value":12341234
},
{
"key":"2",
"value":123412341234
}
],
"titleName":"title 1"
},
{
"title":[
{
"key":"0",
"value":12341
},
{
"key":"1",
"value":123412
},
{
"key":"2",
"value":12
},
{
"key":"3",
"value":12341
}
],
"titleName":"title 2"
}
]
}
This would allow for you to build an object like...
public class YouObjectName{
private ArrayList<Title> listOfTitles;
private String titleName;
//constructor
//getters and setters
}
public class Title{
private String key;
private Integer value;
//constructor
//getters and setters
}
I would consume this with GSON like
new Gson().fromJson(jsonString,YouObjectName.class);
Hope that helps a little.

Related

Google DLP - Can I use a delimiter to instruct DLP infotype detectors to search only inside that for sensitive text?

I have an issue while trying to deidentify some data with DLP using an object mapper to parse the object into string - send it to DLP for deidentification - getting back the deidentified string and using the object mapper to parse the string back to the initial object. Sometimes DLP will return a string that cannot be parsed back to the initial object (it breaks the json format of the object mapper)
I use an objectMapper to parse an Address object to string like this:
Address(
val postal_code: String,
val street: String,
val city: String,
val provence: String
)
and my objectmapper will transform this object into a string eg: "{\"postal_code\":\"123ABC\",\"street\":\"Street Name\",\"city\":\"My City\",\"provence\":\"My Provence\"}" which is sent to DLP and deidentified (using LOCATION or STREET_ADDRESS detectors).
The issue is that my object mapper would expect to take back the deidentified string and parse it back to my Address object using the same json format eg:
"{\"postal_code\":\"LOCATION_TOKEN(10):asdf\",\"street\":\"LOCATION_TOKEN(10):asdf\",\"city\":\"LOCATION_TOKEN(10):asdf\",\"provence\":\"LOCATION_TOKEN(10):asdf\"}"
But there are a lot of times that DLP will return something like
"{"LOCATION_TOKEN(25):asdfasdfasdf)\",\"provence\":\"LOCATION_TOKEN(10):asdf\"}" - basically breaking the json format and i am unable to parse back the string from DLP to my initial object
Is there a way to instruct DLP infotype detectors to keep the json format, or to look for sensitive text only inside \" * \"?
Thanks
There are some options here using a custom regex and a detection ruleset in order to define a boundary on matches.
The general idea is that you require that findings must match both an infoType (e.g. STREET_ADDRESS, LOCATION, PERSON_NAME, etc.) and your custom infoType before reporting as a finding or for redaction. By requiring that both match, you can set bounds on where the infoType can detect.
Here is an example.
{
"item": {
"value": "{\"postal_code\":\"123ABC\",\"street\":\"Street Name\",\"city\":\"My City\",\"provence\":\"My Provence\"}"
},
"inspectConfig": {
"customInfoTypes": [
{
"infoType": {
"name": "CUSTOM_BLOCK"
},
"regex": {
"pattern": "(:\")([^,]*)(\")",
"groupIndexes": [
2
]
},
"exclusionType": "EXCLUSION_TYPE_EXCLUDE"
}
],
"infoTypes": [
{
"name": "EMAIL_ADDRESS"
},
{
"name": "LOCATION"
},
{
"name": "PERSON_NAME"
}
],
"ruleSet": [
{
"infoTypes": [
{
"name": "LOCATION"
}
],
"rules": [
{
"exclusionRule": {
"excludeInfoTypes": {
"infoTypes": [
{
"name": "CUSTOM_BLOCK"
}
]
},
"matchingType": "MATCHING_TYPE_INVERSE_MATCH"
}
}
]
}
]
},
"deidentifyConfig": {
"infoTypeTransformations": {
"transformations": [
{
"primitiveTransformation": {
"replaceWithInfoTypeConfig": {}
}
}
]
}
}
}
Example output:
"item": {
"value": "{\"postal_code\":\"123ABC\",\"street\":\"Street Name\",\"city\":\"My City\",\"provence\":\"My [LOCATION]\"}"
},
By setting "groupIndexes" to 2 we are indicating that we only want the custom infoType to match the middle (or second) regex group and not allow the :" or " to be part of the match. Also, in this example we mark the custom infoType as EXCLUSION_TYPE_EXCLUDE so that it does not report itself:
"exclusionType": "EXCLUSION_TYPE_EXCLUDE"
If you remove this line, anything matching your infoType could also get redacted. This can be useful for testing though - example output:
"item": {
"value": "{\"postal_code\":\"[CUSTOM_BLOCK]\",\"street\":\"[CUSTOM_BLOCK]\",\"city\":\"[CUSTOM_BLOCK]\",\"provence\":\"[CUSTOM_BLOCK][LOCATION]\"}"
},
...
Hope this helps.

Update Json value in json Array in Java

{
"page": {
"size": 2,
"number": 2
},
"places": [
{
"eventName": "XYZ",
"createdByUser": "xyz#xyz.com",
"modifiedDateTime": "2021-03-31T09:59:48.616Z",
"modifiedByUser": "xyz#xyz.com"
}
]}
I am trying to update the "eventName" field with new String. I tried with the following code, It updates the field but returns only four fields in the json array.
public String modifyJson() throws Exception{
String jsonString = PiplineJson.payload(PiplineJson.filePath());
System.out.println(jsonString);
JSONObject jobject = new JSONObject(jsonString);
String uu = jobject.getJSONArray("places")
.getJSONObject(0)
.put("eventName", randomString())
.toString();
System.out.println(uu);
return uu;
}
This is what the above code does.
{
"eventName": "ABCD",
"createdByUser": "xyz#xyz.com",
"modifiedDateTime": "2021-03-31T09:59:48.616Z",
"modifiedByUser": "xyz#xyz.com"
}
I am trying to get the complete json once it updates the eventName filed.
{
"page": {
"size": 2,
"number": 2
},
"places": [
{
"eventName": "ABCD",
"createdByUser": "xyz#xyz.com",
"modifiedDateTime": "2021-03-31T09:59:48.616Z",
"modifiedByUser": "xyz#xyz.com"
}
]}
The problem is the way that you are chaining the operations together. The problem is that you are calling toString() on the result of the put call. The put calls returns the inner JSONObject that it was called on. So you end up serializing the wrong object.
Changing this:
String uu = jobject.getJSONArray("places")
.getJSONObject(0)
.put("eventName", randomString())
.toString();
to
jobject.getJSONArray("places")
.getJSONObject(0)
.put("eventName", randomString());
String uu = jobject.toString();
should work.
That's because you are returning the first element you extracted from "places" array. You should return "jobject.toString()" instead.

Error on JsonElement cannot be convert to JsonObject

so there is a jsonReqObj,
jsonReqObj = {
"postData" : {
"name":"abc",
"age": 3,
"details": {
"eyeColor":"green",
"height": "172cm",
"weight": "124lb",
}
}
}
And there is a save function that will return a string. I want to use that save function, but the input parameter for the save json should be the json inside postData.
public String save(JsonObject jsonReqObj) throw IOException {
...
return message
}
below are my code
JsonObject jsonReqPostData = jsonReqObj.get("postData")
String finalMes = save(jsonReqPostData);
But I am getting the error that
com.google.gson.JsonElement cannot be convert to com.google.gson.JsonObject.
JsonObject.get returns a JsonElement - it might be a string, or a Boolean value etc.
On option is to still call get, but cast to JsonObject:
JsonObject jsonReqPostData = (JsonObject) jsonReqObj.get("postData");
This will fail with an exception if it turns out that postData is a string etc. That's probably fine. It will return null if jsonReqObj doesn't contain a postData property at all - the cast will succeed in that case, leaving the variable jsonReqPostData with a null value.
An alternative option which is probably clearer is to call getAsJsonObject instead:
JsonObject jsonReqPostData = jsonReqObj.getAsJsonObject("postData");
I have validated your JSON file with https://jsonlint.com/ and it looks like the format is incorrect, instead of be:
jsonReqObj = {
"postData": {
"name": "abc",
"age": 3,
"details": {
"eyeColor": "green",
"height": "172cm",
"weight": "124lb",
}
}
}
Should be:
{
"postData": {
"name": "abc",
"age": 3,
"details": {
"eyeColor": "green",
"height": "172cm",
"weight": "124lb"
}
}
}
Maybe thats why you cant convert to an object
Note: I would put this as a comment instead as an answer, but i dont have enought reputation T_T

Creating model for JSON where key is a value in android

I want to create a model from JSON where key is a value. This is the exact issue described, but in iOS. I want a similar solution in Android. Basically I want to have a Decodable equivalent in Android.
I am using GSON to parse JSON to model. As of now, I have compared the JSON key (mentioned in the link) against static values.
JSON :
{
"rows" :
[
{
"_id": "5cdc0ede5c3dcb04bdb3a972",
"emp_code": 187,
"log_id": 361711,
"punch_time": "2019-05-07T04:00:33.000Z",
"pin_type": 1,
"status": 4,
"__v": 0
},
{
"_id": "5cdc40de5c3dcb04bdb3a972",
"emp_code": 111,
"log_id": 361701,
"punch_time": "2019-05-07T04:00:35.000Z",
"pin_type": 101,
"status": 4,
"__v": 0
}
],
"pin_type_text": {
"1": "In Fingerprint",
"4": "In Card",
"101": "Out Fingerprint",
"104": "Out Card"
}
}
The value of pin_type in each row refers to the record in pin_type_text mapped with it's key.
I am using GSON for creating models, and here is the model class :
class MyModel {
var length : Long = 0
var rows = ArrayList<Rows>()
var pin_type_text : String = ""
}
class PinTypeText {
var 1 : String = ""
var 4 : String = ""
var 101 : String = ""
var 104 : String = ""
}
Basically, the keys defined in class PinTypeText are the values of the key 'pin_type' obtained in Rows model as seen in the JSON shared. So in this case, the keys in 'PinTypeText' are dependent on values defined in 'rows'. Hence, i want 'PinTypeText' model to be created with respect to 'pin_type' values from 'Rows' model.
Issue : Suppose in future, the 'pin_type' values - 1, 4, 101, 104 change in the backend, how can I handle such a case without changing my model. As per this model structure, I need to change my model class every time the backend model changes
you can store the item PinTypeText as a JsonElement and not as a custom class,
so your response model will be something like this
public class Response{
#SerializedName("rows")
#Expose
private List<Row> rows = null;
#SerializedName("pin_type_text")
#Expose
private JsonElement pinTypeText;
public List<Row> getRows() {
return rows;
}
public void setRows(List<Row> rows) {
this.rows = rows;
}
public JsonElement getPinTypeText() {
return pinTypeText;
}
public void setPinTypeText(JsonElement pinTypeText) {
this.pinTypeText = pinTypeText;
}
}
and when you want to check the type you can convert it to JsonObject and get the value for the key,
example
pinTypeText= response.getPinTypeText().asJsonObject().get([your pin_type here]).toString()

How to check the if statement value in drools using dialect "Mvel"?

I have a json below
"root":[
{
"refDataId": 1,
"children": [
{
"refDataId": 20
},
{
"refDataId": 99,
"otherValue": "Facility"
}
]
},
{
"refDataId": 2,
"children": [
{
"refDataId": 30
},
{
"refDataId": 99,
"otherValue": "Officer"
}
]
}
]
How to check the value above using the if statement in rule drools?
I edited the question. This is for drools rule
For example my rules is:
rule "test"
when
RuleEngine(inputObject!.adultHealth!.children contains 99)
then
info("children contains value 99");
end
And how to check the value of "refDataId": 99, and "otherValue": "Officer"?
If the value has to get from 2nd child json "refDataId": 2,
You can extract data using any json parser
I have used org.json
The following code tries to find an OFFICER from your json data.
JSONObject obj = new JSONObject(jsonString);
JSONArray objArray = obj.optJSONArray("root");
for (Object jo : objArray) {
JSONObject arrayElement = new JSONObject(jo.toString());
JSONArray childrenArray = arrayElement.getJSONArray("children");
for (Object child : childrenArray) {
JSONObject childJo = new JSONObject(child.toString());
if (Integer.parseInt(childJo.get("refDataId").toString()) == 99) {
if (childJo.get("otherValue").toString().equals("Officer")) {
System.out.println("Success Officer Found !");
}
}
}
}
Looking here Nested JSON iterations using drools Fluent API it seems to me it is enough to create data objects corresponding to structure of your JSON.

Categories