Parsing map JSON value and reinserting back into map - java

I am trying to parse a map and update the value in it...
Here is the content of the .txt file that I have made the hashmap
The first line is the key and the JSON string is the value.
Not_enough_parameters
{"status": false, "errorMessage": "Payload has incorrect amount of parts: expecting: 18, actual:8", "version": "0.97", "coreName": "Patient_Responsibility"}
Here is my parsing code:
parse = params.split("\\|");
String key;
String value;
String value2;
String key2;
String value3;
Map<String, String> predictionFeatureMap = mockconfig.getPredictionFeatureMap();
if(parse.length!=18) {
key = "Not_enough_parameters";
value = predictionFeatureMap.get(key);
Map<?,?> resultJsonObj = new Gson().fromJson(value, Map.class);
key2 = "errorMessage";
value2 = (String) resultJsonObj.get(key2);
value3 = value2.substring(0,61) +parse.length+value2.substring(62);
}
I am sending a payload string named params that is separated by "|" separators. They input must have 18 parameters(18 values in-between the "|" separators). I parse the input and if it does not have enough parameters I get they key containing the string "Not_enough_paramters" and then get its value which is the JSON string.
I then take that JSON string and using Gson create a map out of it.
I did that because I want value to return
{"status": false, "errorMessage": "Payload has incorrect amount of parts: expecting: 18, actual:(params.length)", "version": "0.97", "coreName": "Patient_Responsibility"}
So I want "actual:" to be updated. I get the value from the JSON map for "errorMessage" and using substring I get the index and change the value to update the actual amount of parameters the user put in.
I am not sure how to reinsert the new JSON into the entire JSON string in the JSON map and then into the original map.

So I implemented a solution although I am not sure it is the cleanest and most straight forward.
I still got the substring from the value from the "errorMessage" key in the JSON Map.
I then replaced the value of that key with the new edited JSON.
Then I took the Json Map and converted it into a string.
I then added the new JSON string to the value of the original hashmap
String[] parse;
#PostMapping(value = "/")
public String payloader(#RequestBody String params ) throws IOException{
LOGGER.debug("code is hitting");
String key,key2;
String value,value2,value3;
Map<String, String> predictionFeatureMap = mockconfig.getPredictionFeatureMap();
if(parse.length!=18) {
key = "Not_enough_parameters";
value = predictionFeatureMap.get(key);
Map<String,Object> resultJsonObj = new Gson().fromJson(value, Map.class);
key2 = "errorMessage";
value2 = (String) resultJsonObj.get(key2);
value3 = value2.substring(0,61) +parse.length+value2.substring(62);
resultJsonObj.replace(key2, value3);
String updatedResponse = new Gson().toJson(resultJsonObj,Map.class);
value = updatedResponse;
}
else {
key = params;
value = predictionFeatureMap.get(key);
}
return value;

Related

Best way to compare JSON array with another JSON array with Regex Values?

I have to validate the values of output json file. First validation is all the key value pairs needed are in the file and the second one, values are in the correct format as expected ( say, timestamp, string, integer ...). I cannot compare the values directly with another file having same content as some of the values like timestamp, id are random.
JSON File:
[
{
"metadata": {
"RecordEnd": 19,
"Type": null,
"RecordOffset": 0,
"Character_Set": "UTF-8",
"MsgType": 8,
"Expire": 0,
"Name": "y1",
"delivered": false,
"Timestamp": 1664189426609,
"UserID": "1jnj2232",
"Encoding": 273,
"id": "ID:414d51205120202020210040",
"DType": "type1"
}
]
I have two approches to do this.
Create a hashmap with keys as same in the JSON file and have values as regex patterns and compare each key value pairs with the regex matching the keys.
HashMap<String,String> metaData = new HashMap();
metaData.put("RecordEnd","\\d+");metaData.put("Type","\\w+");
metaData.put("RecordOffset","\\d+");metaData.put("Character_Set","UTF-8");
metaData.put("MsgType","\\d+");metaData.put("Expire","\\w+");
metaData.put("Name","\\w+");metaData.put("delivered","\\w+");
metaData.put("Timestamp","\\d+");metaData.put("UserID","\\w+");
metaData.put("Encoding","\\d+");metaData.put("id","ID\\:\\w+");
metaData.put("DType","type1");
ObjectMapper mapper = new ObjectMapper();
String json = FileUtils.readFileToString(new File(outputJSONFile),"UTF-8");
json = json.substring(1, json.length() - 1);
Map<?, ?> map = mapper.readValue(json, Map.class);
HashMap<String,Object> metaMap = (HashMap<String, Object>) map.get("metadata");
metaMap.entrySet().forEach(e-> {
if (!(e.getValue() == null)) {
if (e.getValue().toString().matches(metaData.get(e.getKey()))) {
log.info(e + "- Matched");
} else {
throw new RuntimeException(
"MetaData key " + e.getKey() + " data is invalid");
}
}
});
Here, if the fields size become larger ( say 40+ fields) , I have to add hashmap values for all the fields , it becomes a tedious process and reduces readability.
Create a static json file with the all the keys and the values in the regex format. Then, compare the two files based on regex of one file to match with another file. I haven't tried this yet.
Is the second approach more efficient or is there a more suitable approach to do this?

iterate through a map of string object that has mutiple values per key

I'm receiving the following JSON object and I'm only interested in the errors. I can log to the console each key and value. The issue is for example 'Email' key has 2 x values, how can i create a map or list so every value has its own key and remove the JSON formatting?
{
"errors":
{
"Email":["'Email' must not be empty.","'Email' is not a valid email address."],
"Company":["'Company' must not be empty."],
"LastName":["'Last Name' must not be empty."],
"Password":["'Password' must not be empty."],
"FirstName":["'First Name' must not be empty."],
"Telephone":["'Telephone' must not be empty."]
},
"title":"One or more validation errors occurred.",
"status":400,
"traceId":"80005307-0001-5d00-b63f-84710c7967bb"
}
In codenameone i'm parsing using JSON parser in to a map of string, object:
Map<String,Object> result = new JSONParser().parseJSON(new InputStreamReader(new ByteArrayInputStream(r.getResponseData()), "UTF-8"));
Map<String,Object> value = (Map<String,Object>) result.get("errors");
for (Map.Entry<String, Object> entry : value.entrySet()) {
Log.p(entry.getKey());
Log.p(entry.getValue().toString())
}
The value of the email field is a list, as indicated by the [] square brackets.
Since it appears that all the fields of errors have lists of strings, you should simple cast to Map<String, List<String>>, so you don't have to cast any further.
Map<String,Object> result = /*result of parsing JSON input*/;
#SuppressWarnings({ "rawtypes", "unchecked" })
Map<String, List<String>> errors = (Map) result.get("errors");
for (Entry<String, List<String>> error : errors.entrySet()) {
String name = error.getKey();
List<String> messages = entry.getValue();
Log.p(name);
for (String message : messages)
Log.p(" " + message);
}
That's your thing, brother, I just changes some names for better readability:
Map<String,Object> errors = (Map<String,Object>) map.get("errors");
Collection<Object> values = errors.values();
values.stream().flatMap(x->((ArrayList<String>)x).stream()).forEach(value -> {
String key = errors.entrySet()
.stream()
.filter(tempEntry -> ((ArrayList<String>)tempEntry.getValue()).contains(value))
.findAny()
.get()
.getKey();
System.out.println(key + value);
});
So ye from that you can create a Collection of entries. Currently we print them, but you can skip ".getKey()" and "System.out" and start adding them to a collection.

JAVA Json object with '=' instead of ':'

I have a string in java, that has a JSON structure, but instead of using ':' my string uses '='. so for example I have this string:
[{
index1 = val1,
index2 = val2,
index3 = val3&val4=inside_value
}]
instead of like this:
[{
index1 : val1,
index2 : val2,
index3 : val3&val4=inside_value
}]
now, I can use some costume parser that I can build, but I guess there is already something that works.
any ideas please?
You can go for custom parsing if the string structure is permanent
String convertToJson="[{"
+"index1 = val1,"
+"index2 = val2,"
+"index3 = val3&val4=inside_value"
+"}]";
String[] split1= convertToJson.split(",");
HashMap<String, String> map=new HashMap<>();
for(String row:split1){
row =row.toLowerCase().replaceAll("[\\[\\]\\{\\}]", "");
String key=row.split("=",2)[0];
String value=row.split("=",2)[1];
map.put(key, value);
}
System.out.println("map :: "+map.toString());
JSONObject json = new JSONObject();
json.putAll( map );
System.out.printf( "JSON:", json.toString() );
It is possible to create hashmap from your string by removing unwanted characters and finally create a JSONObject from the hashmap

Retrieve hashmap data SharedPreferences

I used HashMap to store data which I received using API. After that, I used SharedPreferences to store the received HashMap data. Storing part is done. I can see the number of records which I wanted to store using SharedPreferences.
Here is the code to save data:
if (result != null && result.length() > 0)
{
for (int j = 0; j < result.length(); j++)
{
JSONObject resultObj = result.getJSONObject(j);
String label_id = resultObj.getString("label_id");
String arabic = resultObj.getString("arabic");
String english = resultObj.getString("english");
String key = resultObj.getString("key");
//Create a new model and set the received value
LabelModel labelModel = new LabelModel();
labelModel.setLabelId(label_id);
labelModel.setArabic(arabic);
labelModel.setEnglish(english);
labelModel.setKey(key);
int label = Integer.parseInt(label_id);
//Put the value
map.put(label, labelModel);
}
}
//With the below line, I stored the hashMap data using SharedPreferences
Pref.setValue(mActivity, AppPrefrences.PREF_LABELS, map);
After the above steps, I followed this set of code to set and get the value from SharePreferences, which I stored in application using SharedPreferences.
For that, I used this below code:
public static String PREF_LABELS ="labels";
public static void setValue(#NonNull Context context, String key, Object obj) {
Pref.openPref(context);
Editor prefsPrivateEditor = Pref.sharedPreferences.edit();
prefsPrivateEditor.putString(key, String.valueOf(obj));
prefsPrivateEditor.commit();
prefsPrivateEditor = null;
Pref.sharedPreferences = null;
}
#Nullable
public static String getValue(#NonNull Context context, String key, Object obj) {
Pref.openPref(context);
String result = Pref.sharedPreferences.getString(key, String.valueOf(obj));
Pref.sharedPreferences = null;
return result;
}
Now, I am trying to retrieve the data which I stored in SharedPreferences.
Here is the code I used to retrieve the data:
String labels = Pref.getValue(mActivity, AppPrefrences.PREF_LABELS, "");
When I debug the app, I get values in Labels below format. The same number of records I received.
The format goes like this:
{572=com.*****.landlord.model.LabelModel#23a282e, 598=com.*****.landlord.model.LabelModel#c954fcf, 590=com.*****.landlord.model.LabelModel#2fe3d5c, 103=com.*****..........}
How can I get the each data from this format?
There is no support for HashMap in SharedPreferences. So, you can't save the HashMap by converting it to a string directly, but you can convert it to JSON string. You can use google-gson in this case. Something like this:
First, include the dependency:
compile 'com.google.code.gson:gson:2.8.2'
Saving from HashMap object to preference:
Editor prefsEditor = mPrefs.edit();
Gson gson = new Gson();
String json = gson.toJson(map);
prefsEditor.putString("YourHashMap", json);
prefsEditor.commit();
Get HashMap object from preference:
Gson gson = new Gson();
String json = mPrefs.getString("YourHashMap", "");
HashMap map = gson.fromJson(json, HashMap.class);
Instead convert the map to gson String and store it in preference like this
//convert to string using gson
Gson gson = new Gson();
String mapString = gson.toJson(map);
//save this in the shared prefs
SharedPreferences prefs = getSharedPreferences("test", MODE_PRIVATE);
prefs.edit().putString("yourkey", mapString).apply();
//get from shared prefs in gson and convert to maps again
String storedHashMapString = prefs.getString("yourkey",null);
java.lang.reflect.Type type = new TypeToken<HashMap<String, String>>(){}.getType();
//Get the hashMap
HashMap<String, String> map = gson.fromJson(storedHashMapString, type);
You are getting {572=com.*****.landlord.model.LabelModel#23a282e, 598=com.*****.landlord.model.LabelModel#c954fcf, 590=com.*****.landlord.model.LabelModel#2fe3d5c, 103=com.*****..........} this because Object default toString() method use hashcode.
Storing complex object in SharedPreference is not recommended. SharedPreference don't support HashMap link.
For storing simple object you have to convert the object into String using toString() method.
You can use Gson for converting object to String and that will be a easy solution.
You can also use ObjectOutputStream to write it to the internal memory check this link
You should cast lables string into hashmap object This is one solution. If you want to make it more generic, you can us StringUtils library.
String value = "{first_name = mohit,last_name = mathur,gender = male}";
value = value.substring(1, value.length()-1); //remove curly brackets
String[] keyValuePairs = value.split(","); //split the string to creat key-value pairs
Map<String,String> map = new HashMap<>();
for(String pair : keyValuePairs) //iterate over the pairs
{
String[] entry = pair.split("="); //split the pairs to get key and value
map.put(entry[0].trim(), entry[1].trim()); //add them to the hashmap and trim whitespaces
}
For example, you can switch
value = value.substring(1, value.length()-1);
to
value = StringUtils.substringBetween(value, "{", "}");
and after that
You should cast value in LabelModel
like
LabelModel labels = map.get("598");
SharedPreference doesn't support store map object. https://developer.android.com/reference/android/content/SharedPreferences.Editor.html. So your code just store data obj.toString, that why you see result in debug. If you want to store a map, you can store as json and use put string.

how to Parse Map value Data in android

Map<String, String> map =dataSnapshot.getValue(Map.class);
String MR_ID = map.get("MR_ID");
String JOB_TITLE = map.get("JOB_TITLE");
String JOB_TYPE = map.get("JOB_TYPE");
String Delv_ADDR=map.get("Delv_ADDR");
DataSnapshot { key = platformdb, value =
{MR_RELATIONS={CUSTOMERS={ORDERS={INVENTORY=, Delv_ADDR=D-103
LaxmiNagar New Delhi, ORDER_ID=}}}, MR_SCHEDULE={MR_ID=, JOB_TITLE=,
GEO_LINK=, JOB_TYPE={TSP={TSP_ADDR=, TSP_ID=, GEO_LINK=, TSP_NAME=},
SCC={SCC_ID=, SCC_ADDR=, GEO_LINK=, SCC_NAME=}, CUSTOMER={GEO_LINK=,
CUST_NAME=, CUST_ID=, CUST_ADDR=}}, JOB_ID=, TRANS_SRC=, TRANS_DEST=},
MR_POOL={FREE_MR=, BUSY_MR={77889992222={IS_BUSY=false,
GEO_LINK=8yyttrd}}}} }
This is my Data i am getting in map i want to Parse and and get value of Delv_ADDR But i am unable to get i am getting Null value please suggest me how to get data of that
From the attached input it seems that there is only one entry in the map with key platformdb and value as MR_RELATIONS=....
If you are doing String MR_ID = map.get("MR_ID"); then it will probably return you null as there is no entry in the map with key MR_ID.
What you should be doing instead is retrieve the value against the key by doing the following:
String response = map.get("platformdb");
And then parse this response String to extract the desired values.
Since, response does not seems to be JSON you can try using native String functions.
For example, to extract MR_ID from response you can do the following:
String response = map.get("platformdb");
String MR_ID = response.substring(response.indexOf("MR_ID=") + 6,
response.indexOf("MR_ID=") + response.indexOf(","));
String Delv_ADDR = response.substring(response.indexOf("Delv_ADDR=") + 10,
response.indexOf("Delv_ADDR=") + response.indexOf(","));

Categories