Iterate all json object and replace values - java

I have following JSON:
{
"data":{
"attributes":{
"external-event-url":"http://example.com",
"is-sponsors-enabled":"true",
"is-ticketing-enabled":"true",
"timezone":"UTC",
"name":"${name_variable}",
"ends-at":"2020-01-02T23:59:59.123456+00:00",
"starts-at":"2020-01-01T23:59:59.123456+00:00"
},
"type":"event"
}
}
I have to iterate through json objects and replace the value of variable starts with ${ e.g. ${name_variable}
and new json should be in same format(with replace value of variable mentioned ${})
How do i iterate such complex Json object and replace the values in variables
I've tried below code but not working as expected:
public Map<String, String> mapfillData(String jsonstr) {
Map<String, String> map = new HashMap<String, String>();
try {
JSONObject jsonObject = new JSONObject(jsonstr);
String[] keys = JSONObject.getNames(jsonObject);
for (String key : keys) {
try {
if (jsonObject.get(key).toString().startsWith("${")) {
map.put(key, System.getProperty(jsonObject.get(key).toString()
.replace("${", "").replace("}", "")));
} else {
if(isJSONValid(jsonObject.get(key).toString())){
mapfillData(jsonObject.get(key).toString());
}else{
map.put(key, jsonObject.get(key).toString());
}
}
} catch (Exception e) {
}
}
} catch (JSONException e) {
System.err.printf(jsonstr + " is not valid Json", e);
}
return map;
}
To check whether its a valid JSON Object
public boolean isJSONValid(String test) {
try {
new JSONObject(test);
} catch (JSONException ex) {
// edited, to include #Arthur's comment
// e.g. in case JSONArray is valid as well...
try {
new JSONArray(test);
} catch (JSONException ex1) {
return false;
}
}
return true;
}

Your problem is that while you are trying to recursively process the JSON, at each level of recursion, you're processing a different JSON document and writing data into a different Map.
Your function takes a string and then parses it into a JSONObject. You create a Map to hold some data. The first time through mapfillData, you're only going to find one key, data. Then, assuming that your if logic works correctly (I didn't try to run it), you're going to render the contents of data into another string and recursively call mapfillData.
Now you're in the second call to mapfillData, and you create another Map. This time through you find attributes and call mapfillData a third time. In this third invocation, you find some variables and replace them when writing the values to Map. At the end of the function, you return the Map, but the caller (the second invocation of mapfillData) doesn't do anything with the returned Map, and all your data is lost.
I would:
Parse the JSON once, then recurse through the JSONObject structure. In other words, the recursive function should take JSONObject.
Just replace the JSON elements in-place.
Or, if you want to flatten the elements and collect them into a Map, then instantiate the Map up-front and pass it into the recursive function.

To convert more easily, you can use the Jackson lib to do the hard stuff:
ObjectMapper mapper = new ObjectMapper();
String jsonString = "{
"data":{
"attributes":{
"external-event-url":"http://example.com",
"is-sponsors-enabled":"true",
"is-ticketing-enabled":"true",
"timezone":"UTC",
"name":"${name_variable}",
"ends-at":"2020-01-02T23:59:59.123456+00:00",
"starts-at":"2020-01-01T23:59:59.123456+00:00"
},
"type":"event"
}
}";
// considering JSONObject matches the Json object structure
JSONObject jsonObject = mapper.readValue(jsonString , JSONObject.class);
Then a little bit of reflection to handle any JSON object fields dynamically:
// with parsed JSON to Object in hands
Class<?> clazz = jsonObject.getClass();
for(Field field : clazz.getDeclaredFields()) {
if(!field.getType().getName().equals("String"))
break;
field.setAccessible(true);
String fieldValue = field.getValue().toString();
if(fieldValue.startsWith("${"))
field.set(jsonObject, fieldValue.replace("${", "").replace("}", ""));
else
// desired treatment
}

Related

How to convert string into JSONObject?

I have a string with value abc#xyz.com.
I have to pass this value to server like:
{"email":"abc#xyz.com"}
I am passing value to server like this using okhttp:
Map<String, String> map = new HashMap<>();
map.put("email", email);
new PostMethodWithProgress(login_url, map, this, new Callback()
{
#Override
public void done(String reply)
{
try
{
JSONObject object = new JSONObject(reply);
if (object.getString("status").equals("200"))
{
//Toast Success Message
}
else
{
//Toast Failure Message
}
}
catch (Exception e)
{
Log.e("ASA", "Error is: " + e);
}
}
}).execute();
How do i do it?
You can simply use JSONObject to achieve this
JSONObject jsonObject = new JSONObject();
jsonObject.put("email", "abc#xyz.com");
String result = jsonObject.toString();
Output:
{"email":"abc#xyz.com"}
Use Google Gson convert string to model and model to string easily
ConvertModel convertModel = new Gson().fromJson(reply, ConvertModel .class);
Then you can validate easily
easy way use this code to pass jsonobject as string in okhttp
String jsonString = "";
try {
JSONObject obj = new JSONObject();
obj.put("email", "abc#xyz.com");
obj.put("pwd", "12356");
jsonString = obj.toString();
//out put like this -> {"email":"abc#xyz.com","pwd":"123456"}
Log.d("JsonString__",jsonString);
}catch (Exception e){};
JsonObject is a modifiable set of name/value mappings. Names are unique, non-null strings. Values may be any mix of JSONObject, JSONArray, Strings, Booleans, Integers, Longs, Doubles or NULL.
for your case key is email and value is abc#xyz.com so as I told JsonObject we can put both key and value pair like below -
JsonObject object = new JsonObject();
object.put("email","abc#xyz.com");
If we convert above JsonObject to string then its value would be -
{"email":"abc#xyz.com"}
hope this will help you.
try out this code with your data.
/**
* This method is used to create text size and color code json and store it in json object.
*
* #param textSize text size entered into edit text.
* #param colorOfPreview text color of custom text color.
* #return return json object of created text size and color.
*/
private String createJSONObject(String textSize, int colorOfPreview) {
JSONObject jsonObject = new JSONObject();
try {
// put your values here
jsonObject.put("textSize", textSize);
jsonObject.put("textColor", colorOfPreview);
return jsonObject.toString();
} catch (JSONException e) {
e.printStackTrace();
}
return jsonObject.toString();
}

How to remove this error -> Json parsing error: Value success at response of type java.lang.String can't be converted to JSONArray

I'm getting JSON parsing error while running my app
Below mentioned the code where I'm facing the error and the json url https://zactra.com/blackboard/teacher/auth/email/check/numankhan2754#gmail.com
MyHttpHandler myhttp = new MyHttpHandler();
String Newurl = url + "auth/email/check/"+email+"/";
// call MyServiceCall method from Myhttphandler class
String jsonstng = myhttp.MyServiceCall(Newurl);
Log.e(TAG, "Response From URL: " + jsonstng);
if (jsonstng != null) {
try {
JSONObject jsonObject = new JSONObject(jsonstng);
//getting JSON array node
JSONArray jsonArray = jsonObject.getJSONArray("response");
// Looping through all data from json
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject loopjsonObject = jsonArray.getJSONObject(i);
myid = loopjsonObject.getString("response");
// tmp hash map for single contact
HashMap<String, String> mydata = new HashMap<>();
// adding each child node to HashMap key => value
mydata.put("response", myid);
mydatalist.add(mydata);
}
} catch (final JSONException e) {
Log.e(TAG, "Json parsing error: " + e.getMessage());
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(StartMainActivity.this, "JSON parsing error", Toast.LENGTH_SHORT).show();
}
});
}
} else {
Log.e(TAG, "Couldn't get json from server.");
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(StartMainActivity.this, "Couldn't get json from server. Check LogCat for possible errors!", Toast.LENGTH_SHORT).show();
}
});
}
Response From URL: {"response":"success"}
Json parsing error: Value success at response of type java.lang.String cannot be converted to JSONArray
{"response":"success"} is a JSONObject but you are treating it as JSONArray.
JSON array is always wrapped with []
Example : ["a", "b", "c"] OR something like array of JSONObjects . For example : [{"key":"value"}, {"key","value"}] . Many combinations are possible but most importantly it should start with []
Well
'success'
is not a json array.
an example of a json array is the following
"cars":[ "Ford", "BMW", "Fiat" ]
that is why it cannot be parsed.
the upper example 'cars' array has String values. so String Objects.
In your example you have after the jsonArray a for loop for the jsonArray
for (int i = 0; i < jsonArray.length(); i++)
there you say that you expect JSONObject
so the format that you are waiting is
{"response":[ {"response":"success"},{"response":"success"},{"response":"success"} ]}
which i believe is not the one you finally want :P.
You also create a new HashMap<>() inside the loop. (read about HashMap because your implementation does not support the same key usage ex. cannot have a hashmap with two string objects with same key 'response')
do not make only checks for null checks, do also checks if the string is blank.
First, define the correct format of the response from your service, then the correct implementation for you to capture your data and search the web so that the response to be parsed to an object by the use of a library like jackson.
Regards!
Ps if you want to handle this response,
then
String jsonstng = "{\"response\":\"success\"}";//your service response
String responseValue = "fail";
if (jsonstng != null) {
try {
JSONObject jsonObject = new JSONObject(jsonstng);
if (jsonObject.length() > 0 && jsonObject.has("response")) {
responseValue = jsonObject.getString("response");
}
} catch (final JSONException e) {
//log and handle error
}
}
System.out.println(responseValue);
may be enough

How to fix 'JsonNull cannot be cast to JsonObject'

I call a post API which responds with details on specific addresses, however some of the responses that get returned have no data so they'll be returned as null. How do I stop the casting error in my code?
I currently only get the data as a Json Object and I'm not sure how to rework my code that so when a JsonNull Element gets returned I can handle that data.
JsonElement element = new JsonParser().parse(jsonString);
JsonObject jsonObject = element.getAsJsonObject();
jsonObject = jsonObject.getAsJsonObject("response"); // This is either an object or it is null
String buildName = jsonObject.get("buildingName").getAsString();
String buildNum = jsonObject.get("premisesNumber").getAsString();
String streetName = jsonObject.get("streetName").getAsString();
What I expect to be returned would be either the address details for valid addresses or no information at all for the invalid addresses.
The error that gets produced is this:
java.lang.ClassCastException: com.google.gson.JsonNull cannot be cast to com.google.gson.JsonObject
Before getAsString() check for isJsonNull(). It'll return true if object is Null.
You can rewrite your code as below
String buildName= (jsonObject.get("buildingName").isJsonNull ? null : jsonObject.get("buildingName").getAsString());
Normally is a good idea validate the data is JSON valid
public static boolean isJSONValid(String test) {
try {
new JSONObject(test);
} catch (JSONException ex) {
try {
new JSONArray(test);
} catch (JSONException ex1) {
return false;
}
}
return true;
}
Function above will return you true in case the string is a valid JSON object(could be an object or an array of objects).
After that you can continue parsing using Jackson lib or the GSON lib

how to compare array from sqlite with contents with json array

Hi I´m having a problems with the best strategy to compare an array from an sqlite database and a json array coming from a webservice response . Please tell me the best way to compare this two arrays . Here is my code :
public void getAllElements() {
Map<String, String> map = new HashMap<String, String>();
try {
//select all query
db.open();
Cursor cc= db.getAllEntries();
try {
// looping through all rows and adding to list
if (cc.moveToFirst()) {
do {
map.put("ID",cc.getString(cc.getColumnIndex(DbHelper.ENTRY_ID)));
} while (cc.moveToNext());
}
} finally {
try { cc.close(); } catch (Exception ignore) {}
}
} finally {
try { db.close(); } catch (Exception ignore) {}
}
// return list
}
protected String doInBackground(String... params) {
// Creating service handler class instance
JSONParser jParser = new JSONParser();
DefaultHttpClient client = new DefaultHttpClient(); // Thread
String uri = "url";
HttpGet httpget = new HttpGet(uri);
httpget.setHeader("Cookie", cookie);
try {
response = client.execute(httpget);
// response
String res = EntityUtils.toString(response.getEntity());
// jarray with the json responde
jArr = new JSONArray(res);
System.out.println("response" + jArr);
for (int i = 0; i < jArr.length(); i++) {
// create json object
JSONObject jsonObject = jArr.getJSONObject(i);
// easy parse fields
String vid = jsonObject.getString("vid");
String nid = jsonObject.getString("nid");
// uid value
String field_text = jsonObject.getString("field_text");
String field_edit_ts = jsonObject.getString("field_editts");
String field_deleted_flag = jsonObject.getString("field_deleted");
String field_device_name = jsonObject.getString("field_devicename");
String field_creation_ts = jsonObject.getString("field_creationts");
String field_device_key = jsonObject.getString("field_devicekey");
}
} catch(Exception e){
}
}
I'd recommend wrapping both your Database and your JSON data in a class and implementing the equals(Object) method.
For your JSON data, once you have a class (as above), I'd use GSON (https://code.google.com/p/google-gson/) to convert directly to Objects
Then for your comparison, convert either your database or JSON data into a List (something from Collections, or a HashTable/HashMap (quicker for searching)) and use the Collections.contains(Object) (on the List) method and a contains count which you compare against the list's size. Here's an example, fill in the blanks:
List<YourObject> dbDataList = new ArrayList<YourObject>(Arrays.asList(yourDatabaseDataArray));
int containsCount = 0;
for (YourObject o : yourJsonDataArray){
if (dbDataList.contains(o))
containsCount ++;
}
// Success condition is up to you, I'm just comparing the sizes
if (containsCount == dbDataList.size()){
// Success!
} else {
// Failure
}
Map<String, String> map = new HashMap<String, String>();
You are creating HasMap which contains two string-variable(key and value). It is possible to search the values with keys for exemple but you cannot sort HashMap. (Array)List could be sorted, as Artyom said.
map.put("ID",cc.getString(cc.getColumnIndex(DbHelper.ENTRY_ID)));
You are putting string "ID" to the key of every value of the map. Change that to List and sort it with Collections.sort(list,Comparator).
You could create class to save state of data you have got and override method equals for compare in your class.
Further, for save data use ArrayList.
For compare used next code.
Collection<YourObject> one= new ArrayList(Arrays.asList(obj1, obj2, obj3));
Collection<YourObject> two = new ArrayList(Arrays.asList(obj1, obj2, obj3));
one.equals(two)

Iterate Json data from web service in correct order

I have a response coming from a web service, data is in JSON form.
JSONObject event:-
{
"15:00":{"type":1,"status":null,"appointment_id":null},
"16:00":{"type":1,"status":null,"appointment_id":null},
"17:00":{"type":1,"status":null,"appointment_id":null},
"18:00":{"type":1,"status":"1","appointment_id":5}
}
I don't know the key values, they are random. So when i iterate the data using iterator by fetching keys and hasNext(). It returns the data but changes the order of coming data.
Iterator AppoinmentIter = event.keys();
while(AppoinmentIter.hasNext()){
String appointmentTime = (String)AppoinmentIter.next();
JSONObject appointmentDetails = event.getJSONObject(appointmentTime);
}
I want the data in exact order in which it is coming.
I checked this link, it suggests to use LinkedHashMap. But here they are inserting the value by keys. And i don't know the keys in my data. So how can i iterate the data in correct order. Please help..
That's not how JSON works. It assumes order doesn't matter unless you have an array. If you want order to matter, you're using the wrong format- you need yo use an array of times->values rather than just times->value.
For your particular application, you can get the set of keys, then sort them with a custom comparator that uses the value parsed as a time to order them. But the built in libraries won't do it for you, because you aren't using JSON as its designed.
Vikas, as far as i understood your problem i managed to retrieve json object in expected format, hope this will help you. Enjoy!!
String s = "{ \"15:00\":{\"type\":1,\"status\":null,\"appointment_id\":null},\"16:00\":{\"type\":1,\"status\":null,\"appointment_id\":null},\"17:00\":{\"type\":1,\"status\":null,\"appointment_id\":null},\"18:00\":{\"type\":1,\"status\":\"1\",\"appointment_id\":5}}";
try {
JSONObject jobj = new JSONObject(s);
Iterator iter = jobj.keys();
while(iter.hasNext()){
String appointmentTime = String.valueOf(iter.next());
aRRaY.add(appointmentTime);
}
Collections.sort(aRRaY);
for(String key : aRRaY){
JSONObject appointmentDetails = jobj.getJSONObject(key);
System.out.println(key +" ----- "+appointmentDetails);
}
}
catch (JSONException e) {
e.printStackTrace();
}
I don't know the implementation you have done, and what 3pp you involved. But anyway, try below codes, you would get what you want.
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map.Entry;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
public class Test {
private static final ObjectMapper mapper = new ObjectMapper();
public static void main(String[] args) {
String json = "{"
+ "\"15:00\":{\"type\":1,\"status\":null,\"appointment_id\":null}, "
+ "\"16:00\":{\"type\":1,\"status\":null,\"appointment_id\":null},"
+ "\"17:00\":{\"type\":1,\"status\":null,\"appointment_id\":null},"
+ "\"18:00\":{\"type\":1,\"status\":\"1\",\"appointment_id\":5}"
+ "}";
LinkedHashMap<String, LinkedHashMap<String, Integer>> fromJSON = fromJSON(
json, LinkedHashMap.class);
for (Entry<String, LinkedHashMap<String, Integer>> entry : fromJSON
.entrySet()) {
System.out.print(entry.getKey());
System.out
.println(" || status = " + entry.getValue().get("status"));
}
}
public static <T> T fromJSON(String input, Class<T> clazz) {
try {
return mapper.readValue(input != null ? input : "null", clazz);
} catch (JsonParseException e) {
throw new RuntimeException(e);
} catch (JsonMappingException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

Categories

Resources