Parse string to LinkedTreeMap<String, Object> - java

How can I parse a key-value pair which I know is result of toString() method of a LinkedTreeMap (it's in some inaccessible code) to a LinkedTreeMap<String, Object>?
Sample string which I would like to convert to : LinkedTreeMap<String, Object>
{Path=z.jpg.json, ImageProperties={Owner=Jack, ImageQuality=6}}
Also I would be happy if I can convert it JSON

You can transform your toString() value to JSON format:
String toStringValue = "{Path=z.jpg.json, ImageProperties={Owner=Jack, ImageQuality=6}}";
String jsonValue = toStringValue.replace("{","{\").replaceAll(",\\s+","\", \"").replace("=","\":\"").replace("}","\"}");
and then this string could be parsed by any json parser.

I m not sure what exactly you want. But I think you can make use of something like thisnew JSONObject(map); .Also please elaborate with some input and output if this doesn't help

I found this method which converts key-value string to JSON, recursively:
public static JSONObject convertKeyValueToJSON(LinkedTreeMap<String, Object> ltm) {
JSONObject jo=new JSONObject();
Object[] objs = ltm.entrySet().toArray();
for (int l=0;l<objs.length;l++)
{
Map.Entry o= (Map.Entry) objs[l];
try {
if (o.getValue() instanceof LinkedTreeMap)
jo.put(o.getKey().toString(),convertKeyValueToJSON((LinkedTreeMap<String, Object>) o.getValue()));
else
jo.put(o.getKey().toString(),o.getValue());
} catch (JSONException e) {
e.printStackTrace();
}
}
return jo;
}

Related

JSON parameter is like nothing I have seen

I'm working on some JSON converting to POJO and the server I'm getting response of is sending a JSON like this:
"Availability":{
"StatusCode":"A",
"BreakDown":{
"2017-10-27":"A"
}
}
How can I save this ( "2017-10-27":"A" )? It changes with each of my request so it should be dynamic! Is it even possible?
If you are going the value currently represented as "2017-10-27":"A", you have to know it is hold in the variable "BreakDown". So you need to query this variable with jsonPath: $.Availability.BreakDown.
it will give this JSON object:
{"2017-10-27":"A"}
Hope it answer your question
The first answer is pretty accurate but to extract the key and value without directly referencing is the target since they are dynamic.
var x = obj.Availability.Breakdown;
for(var key in x){
console.log(key);
console.log(x[key]);
}
This way you get the key and the value both and use it as you like.
Plus, if there are multiple key-value pair inside var x then they can also be reached with this loop.
Assuming that with "should be dynamic" you mean that the content that you want to save (the one inside BreakDown) could change (even the type) for each request and assuming that your example of the json is:
Test.json:
{
"StatusCode":"A",
"BreakDown":{
"2017-10-27":"A"
}
}
You could use the Gson library to get the info that you want. Because every class has Object as a superclass, you could deserialize your json as a Map<Object, Object>.
public static void main(String args[]) {
Gson gson = new Gson();
Map<Object, Object> breakDown=null;
String filename="/.../Test.json";
JsonReader reader = null;
try {
reader = new JsonReader(new FileReader(filename));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
final Type type = new TypeToken<Map<Object,Object>>() {}.getType();
Map <Object,Object> conv= gson.fromJson(reader, type);
for (Map.Entry<Object, Object> entry : conv.entrySet())
{
System.out.println(entry.getKey() + "/" + entry.getValue());
if(entry.getKey().equals("BreakDown"))
{
breakDown= (Map<Object, Object>) entry.getValue();
}
}
if(breakDown!=null){
Map.Entry first= breakDown.entrySet().iterator().next();
System.out.println(first.getKey());
System.out.println(first.getValue());
}
}
The Map<Object, Object> breakDown map is also of Objects because I'm assuming that the key and the value could be different of the example that you posted. Otherwise, if the key is always a date and the value a string, can be defined as Map<Date, String> breakDown.

How to convert JSON String to Map

sorry for duplicating the question, but my problem is other.
I have JSON parser method where I parse from json-string to map. But json-string has a value which is json-string too. Something like that:
{
"status_code":"255",
"data":"{\"user\":{\"idpolzovatel\":1,\"id_poluch_tip\":1,\"fio_polzovatel\":\"Andrew Artificial\",\"login\":\"imi\",\"parol\":\"698d51a19d8a121ce581499d7b701668\",\"key\":null,\"nachalnik\":1,\"buhgalter\":0,\"delopr\":1},\"token\":\"230047517dd122c8f8116a6fa591a704\"}",
"message":"Successfull!"
}
So, my parse-method:
public Map<String, String> convertToMapFromJSON(String res){
ObjectMapper objectMapper = new ObjectMapper();
Map<String, String> response = new HashMap<String, String>();
try {
response = objectMapper.readValue(res, new TypeReference<Map<String, String>>);
int t = 0;
} catch (IOException e) {
e.printStackTrace();
}
return response;
}
I get response in client:
ResponseEntity<String> responseEntity = restTemplate.postForEntity(REST_SERVICE_URI + "/auth/", data, String.class);
get body
String res = responseEntity.getBody();//получаем тело запроса в формате JSON
then use those method:
Map<String, String> response = convertToMapFromJSON(res);
Map<String, String> data1 = convertToMapFromJSON(response.get("data"));
Map<String, String> userDetailes = convertToMapFromJSON(data1.get("user"));
but, when I use last method data1.get("user"); I get exception:
java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to java.lang.String
ok, got it. So, data1.get("user") isn't a string, it's linkedHashMap. So, I could do this then:
Map<String, String> userDetailes = data1.get("user");
? But then I get the error, where IDE say me, that data1.get("user") is a string.
Screenshot from debugger:
So, how can I get this LinkedHashMap with my userdata? Sorry, for my english. Thank you.
Java apply type erasure for generics. It checks type correctness at compile time and then remove generic signature in compile code (ByteCode). Therefore, there's no check at runtime.
See this example which have same behaviour as your JSON library:
/** Returns a generic map which all keys are string but not values **/
T <T extends Map> raw(Class<T> clazz) {
Map object = new LinkedHashMap();
object.put("string", "This is a String");
object.put("map" , new LinkedHashMap());
return (T) object;
}
Here is your code:
/** codes you try to execute/write **/
void withStringValues() {
Map<String,String> object = raw(Map<String,String>.class);
String string = object.get("string"); // Ok
String map = object.get("map"); // ClassCastException
Map map = object.get("map"); // Doesn't compile
}
As you can see the call to raw is considered valid as compiled code don't check for generics. But it makes an invalid and implicit cast from Map to Map<String,String> which actually doesn't occured in compiled code.
Generics are remove and is the compiled version:
void withTypeErasure() {
Map object = raw(Map.class);
String string = (String) object.get("string");
String map = (String) object.get("map");
}
As you can see, Java compiler has removed all generic and adds necessary casts. You can see what's going wrong here.
Your real code must look like this:
void withRealValues() {
Map<String,Object> object = raw(Map<String,Object>.class);
String string = (String) object.get("string"); // Ok
Map<String,Object> map = (Map) object.get("map"); // Ok
}
Looks like ObjectMapper has decoded the string to be of JSON format and has parsed it for you. You could just add a new method to parse (data1.get("user")) which returns a Map.

How to parse JSON with JAVA when there are random key names

How do I convert some JSON to a POJO when I don't know the name of a key?
This is my POJO:
public class Summoner {
private Details summonerDetails;
public Details getSummonerDetails() {
return summonerDetails;
}
public void setSummonerDetails(Details summonerDetails) {
this.summonerDetails = summonerDetails;
}
}
The Details class have variables like id, name, etc. -> No issues here
This is the line in my Main class where I try to map the JSON to a POJO:
Summoner test = new ObjectMapper().readValue(json, Summoner.class);
this is a JSON response example I receive:
{
"randomName":{
"id":22600348,
"name":"Ateuzz",
"profileIconId":546,
"summonerLevel":30,
"revisionDate":1378316614000
}
}
if my POJO Details member variable name is "randomName", above code will work. but when I get a response with a different name than "randomName", it doesn't. How do I make my code work for random names?
I'm using Jackson
I'm sorry I can't make a little more clear my issue.
I have solution using not only jackson API but with the use of org.json API also.
String str = "{\"randomName\":{\"id\":22600348,\"name\":\"Ateuzz\",\"profileIconId\":546,\"summonerLevel\":30,\"revisionDate\":1378316614000}}";
JSONObject json = new JSONObject(str);
Iterator<?> keys = json.keys();
while(keys.hasNext())
{
String key = (String)keys.next();
Details test = new ObjectMapper().readValue(json.getJSONObject(key).toString(), Details.class);
}
Here i have use another JAVA Json API to convert your string into jsonObject and than iterate it to get your first key value and map that to your class Details.
I assume that your json format is same as you have mention in your question.
May this will help you.
Using Jackson:
String json = "{\"randomName\":{\"id\":22600348,\"name\":\"Ateuzz\",\"profileIconId\":546,\"summonerLevel\":30,\"revisionDate\":1378316614000}}";
try
{
#SuppressWarnings("unchecked")
Map<String, Map<String, Object>> map = (Map) new ObjectMapper().readValue(json, Map.class);
for(String key : map.keySet())
{
Map<String, Object> submap = map.get(key);
System.out.println(key + ":");
for(String k : submap.keySet())
{
System.out.println("\t" + k + ": " + submap.get(k));
}
}
}
catch(IOException e)
{
e.printStackTrace();
}

Convert JSON object with duplicate keys to JSON array

I have a JSON string that I get from a database which contains repeated keys. I want to remove the repeated keys by combining their values into an array.
For example
Input
{
"a":"b",
"c":"d",
"c":"e",
"f":"g"
}
Output
{
"a":"b",
"c":["d","e"],
"f":"g"
}
The actual data is a large file that may be nested. I will not know ahead of time what or how many pairs there are.
I need to use Java for this. org.json throws an exception because of the repeated keys, gson can parse the string but each repeated key overwrites the last one. I need to keep all the data.
If possible, I'd like to do this without editing any library code
As of today the org.json library version 20170516 provides accumulate() method that stores the duplicate key entries into JSONArray
JSONObject jsonObject = new JSONObject();
jsonObject.accumulate("a", "b");
jsonObject.accumulate("c", "d");
jsonObject.accumulate("c", "e");
jsonObject.accumulate("f", "g");
System.out.println(jsonObject);
Output:
{
"a":"b",
"c":["d","e"],
"f":"g"
}
I want to remove the repeated keys by combining their values into an array.
Think other than JSON parsing library. It's very simple Java Program using String.split() method that convert Json String into Map<String, List<String>> without using any library.
Sample code:
String jsonString = ...
// remove enclosing braces and double quotes
jsonString = jsonString.substring(2, jsonString.length() - 2);
Map<String, List<String>> map = new HashMap<String, List<String>>();
for (String values : jsonString.split("\",\"")) {
String[] keyValue = values.split("\":\"");
String key = keyValue[0];
String value = keyValue[1];
if (!map.containsKey(key)) {
map.put(key, new ArrayList<String>());
}
map.get(key).add(value);
}
output:
{
"f": ["g"],
"c": ["d","e"],
"a": ["b"]
}
In order to accomplish what you want, you need to create some sort of custom class since JSON cannot technically have 2 values at one key. Below is an example:
public class SomeClass {
Map<String, List<Object>> values = new HashMap<String, List<Object>>();
public void add(String key, Object o) {
List<Object> value = new ArrayList<Object>();
if (values.containsKey(key)) {
value = values.get(key);
}
value.add(o);
values.put(key, value);
}
public JSONObject toJson() throws JSONException {
JSONObject json = new JSONObject();
JSONArray tempArray = null;
for (Entry<String, List<Object>> en : values.entrySet()) {
tempArray = new JSONArray();
for (Object o : en.getValue()) {
tempArray.add(o);
}
json.put(en.getKey(), tempArray);
}
return json;
}
}
You can then retrieve the values from the database, call the .add(String key, Object o) function with the column name from the database, and the value (as the Object param). Then call .toJson() when you are finished.
Thanks to Mike Elofson and Braj for helping me in the right direction. I only wanted to have the keys with multiple values become arrays so I had to modify the code a bit. Eventually I want it to work for nested JSON as well, as it currently assumes it is flat. However, the following code works for what I need it for at the moment.
public static String repeatedKeysToArrays(String jsonIn) throws JSONException
{
//This assumes that the json is flat
String jsonString = jsonIn.substring(2, jsonIn.length() - 2);
JSONObject obj = new JSONObject();
for (String values : jsonString.split("\",\"")) {
String[] keyValue = values.split("\":\"");
String key = keyValue[0];
String value = "";
if (keyValue.length>1) value = keyValue[1];
if (!obj.has(key)) {
obj.put(key, value);
} else {
Object Oold = obj.get(key);
ArrayList<String> newlist = new ArrayList<String>();
//Try to cast as JSONArray. Otherwise, assume it is a String
if (Oold.getClass().equals(JSONArray.class)) {
JSONArray old = (JSONArray)Oold;
//Build replacement value
for (int i=0; i<old.length(); i++) {
newlist.add( old.getString(i) );
}
}
else if (Oold.getClass().equals(String.class)) newlist = new ArrayList<String>(Arrays.asList(new String[] {(String)Oold}));
newlist.add(value);
JSONArray newarr = new JSONArray( newlist );
obj.put(key,newarr);
}
}
return obj.toString();
}

how do I find out a JSON Object return JSON Array or string in android

I have a json like the following. how do I find out a JSON Object return JSON Array or string in android.
{
"green_spots": [
......
],
"yellow_spots": "No yellow spot available",
"red_spots": "No red spot available"
}
The JSON objects retrurn Array when values is present else return a String like "No green/red/yellow spot available". I done the with following way. but is there any other way to do? because alert string is changed the If will not work.
JSONObject obj = new JSONObject(response);
String green = obj.getString("green_spots");
// Green spots
if ("No green spot available".equalsIgnoreCase(green)) {
Log.v("search by hour", "No green spot available");
} else {
JSONArray greenArray = obj.getJSONArray("green_spots");
....
}
Object object = jsonObject.get("key");
if (object instanceof JSONObject) {
// It is json object
} else if (object instanceof JSONArray) {
// It is Json Array
} else {
// It is a String
}
You can use instanceof
instead of getString do just obj.get which will return an Object, check if the object is instanceof String or JSONArray
EDIT:
here is a bit of sample code to go with this:
Object itineraries = planObject.get("itineraries");
if (itineraries instanceof JSONObject) {
JSONObject itinerary = (JSONObject) itineraries;
// right now, itinerary is your single item
}
else {
JSONArray array = (JSONArray) itineraries;
// do whatever you want with the array of itineraries
}
JSONObject obj = new JSONObject(response);
JSONArray greenArray = obj.getJSONArray("green_spots");
if(greenArray!=null){
do your work with greenArray here
}else{
Log.v("search by hour", "No green spot available");
}
Simple just print the object like Log.e("TAG","See>>"JsonObject.toString);
if response is in {} block then it is object if it is in [] its array
Warning: This information may be superfluous, but it might prove to be an alternative approach to this problem.
You can use Jackson Object Mapper to convert a JSON file to a HashMap.
public static HashMap<String, Object> jsonToHashMap(
String jsonString) {
Map<String, Object> map = new HashMap<String, Object>();
ObjectMapper mapper = new ObjectMapper();
try {
// convert JSON string to Map
map = mapper.readValue(jsonString,
new TypeReference<HashMap<String, Object>>() {
});
} catch (Exception e) {
e.printStackTrace();
}
return (HashMap<String, Object>) map;
}
This automatically creates a HashMap of appropriate objects. You can then use instanceof or figure out another way to use those objects as appropriate/required.

Categories