I have a String which is in JSON format. I need to sort this JSON string using attributes but am unable to do it. JSON String is created by reading a CSV file. I do not want to read the CSV again and have to implement it using JSON String only. Is there a way to do that? Please let me know.
JSON String format is :
[
{
"address": "some address",
"name": "some name",
"phone": "some phone",
"age": "some age",
"SSN": "some SSN"
},
{
"address": "abc",
"name": "def",
"phone": "ghi",
"age": "jkl",
"SSN": "mno"
}
]
Please explain.
You can convert the JSONstring into a TreeMap with a Comparator you implement to compare by value, and then convert this TreeMap back to JSON.
See how to create a value Comparator here:
http://www.programcreek.com/2013/03/java-sort-map-by-value/
And then use ObjectMapper to convert the JSON into a map the the map back to JSON:
String json = "{\"address\" : \"def\","
+ "\"name\" : \"ghi\","
+ "\"phone\" : \"jkl\","
+ "\"age\" : \"def\","
+ "\"SSN\" : \"abc\"}";
Map<String, String> jsonMap = new HashMap<String, String>();
ObjectMapper mapper = new ObjectMapper();
jsonMap = (mapper.readValue(json, Map.class));
Comparator<String> comparator = new ValueComparator(jsonMap);
Map<String, String> treeMap = new TreeMap<String, String>(comparator);
treeMap.putAll(jsonMap);
String sortedJson = mapper.writeValueAsString(treeMap);
System.out.println(sortedJson);
Result:
{"SSN":"abc","address":"def","name":"ghi","phone":"jkl"}
Comparator:
public class ValueComparator implements Comparator<String> {
Map<String, String> map = new HashMap<String, String>();
public ValueComparator(Map<String, String> map){
this.map = map;
}
#Override
public int compare(String s1, String s2) {
return map.get(s1).compareTo(map.get(s2));
}
}
Related
I have spent a few days googling this various ways and don't see any that give examples of using HashMap - instead they all refer to Jackson or GSON. I am not able to use these as they cause an issue in Jenkins that will not be addressed (basically everything is super locked down and the work place will not "open" up alternatives)
I have a JSON body that I am attempting to send to a create record API.
For simple JSON body the process is pretty straightforward:
Desired JSON:
{
"owner": {
"firstName": "Steve",
"lastName": "Guy",
"Hair": "brown",
"Eyes": "yes"
"etc": "etc"
},
"somethingElse": "sure"
}
would look like
Map<String,Object> jsonRequest = new HashMap<>();
Map<String,String> ownerMap = new HashMap<>();
HashMap<Object, String> OwnerMap = new HashMap<Object, String>;
OwnerMap.put("firstName","Steve");
OwnerMap.put("lastName","Guy");
OwnerMap.put("Hair","brown");
OwnerMap.put("Eyes","yes");
OwnerMap.put("etc","etc");
jsonRequest.put("owner", OwnerMap);
jsonRequest.put("somethingElse", "sure");
Easy enough
If the JSON gets slightly more complex, I can't seem to figure it out.. and again I cannot use any other dependency for this.
so if I have a JSON Body that I need to send :
{
"customer": {
"address": [
{
"address": "Blah"
}
]
},
"anotherThing": "thing"
}
the same pattern does not work.
Map<String,Object> jsonRequest = new HashMap<>();
Map<String,String> ownerMap = new HashMap<>();
HashMap<Object, String> addressMap = new HashMap<Object, String>;
addressmap.put("address","Blah");
jsonRequest.put("address", addressMap);
jsonRequest.put("owner", OwnerMap);
jsonRequest.put("anotherThing", "thing");
returns as:
{
"owner": {
},
"anotherThing": "thing",
"address": {
"address": "Blah"
}
}
You seem to assume that the inner (for want of a better word) Maps need to be Map<*, String>, and that Map and String are the only things which extend Object.
Something like the following should work fine:
Map<String, Object> json = new HashMap<>();
Map<String, Object> customer = new HashMap<>();
// Could make this a Map<String, Object>[] (array) depending
// on json library used... You don't specify.
List<Map<String, Object>> address = new ArrayList<>();
Map<String, Object> innerAddress = new HashMap<>();
innerAddress.put("address", "Blah");
address.add(innerAddress);
customer.put("address", address);
json.put("customer", customer);
json.put("anotherThing", "thing");
I have a JSON that I'm getting from some external system. I need to convert that JSON into key value based on my system mapping. For instance:
JSON from external system:
[{
"name": "Tim",
"address": "New York",
"education" : {
"university": "XYZ"
}
},
{
"name": "Steve",
"address": "UK"
}]
I have following mapping that we need to use:
{
"name": "firstName",
"address": "location",
"university": "college"
}
i.e name to be mapped to firstName and address to be mapped to location. And finally, my processed mapped will look like:
[{
"firstName": "Tim",
"location": "New York"
"education" : {
"college": "XYZ"
}
},
{
"firstName": "Steve",
"location": "UK"
}]
What can be the best way to achieve this? Should I use normal hashmap operations or is there any other efficient way. I was checking JSONNode for this purpose, but the approach was similar to hash map. Is there any utility I can use to traverse tree like json map and replace the key?
I'm a fan of Jackson which you can use to traverse the JSON. As you do so, populate a list of maps, using your system mapping to replace whatever keys are encountered that have a mapping, leaving the others as is. At the end, dump the list of maps back out as JSON.
Edit: adding code example below
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import java.io.IOException;
import java.util.*;
public class ReplaceKeys {
private static final ObjectMapper mapper = new ObjectMapper();
private static Map<String, String> keymap;
static {
try {
// Create the key map based on the json provided by OP
keymap = mapper.readValue("{\n" +
"\"name\": \"firstName\",\n" +
"\"address\": \"location\",\n" +
"\"university\": \"college\"\n" +
"}", Map.class);
} catch (IOException e) {
System.out.println("whoops");
}
}
public static String mapKeys(String input) throws IOException {
// Assume the input is an array and therefore so is the output.
List<Map<String, Object>> output = new ArrayList<>();
ArrayNode inputArray = (ArrayNode) mapper.readTree(input);
for (JsonNode node : inputArray) {
output.add(mapKeys(node));
}
return mapper.writeValueAsString(output);
}
private static Map<String, Object> mapKeys(JsonNode node) {
Map<String, Object> map = new HashMap<>();
for (Iterator<String> iterator = node.fieldNames(); iterator.hasNext(); ) {
String key = iterator.next();
key = keymap.containsKey(key) ? keymap.get(key) : key;
for (JsonNode child : node) {
if (node.isValueNode()) {
// This is coercing everything to a String. You could dig into using
// proper types based on node.getNodeType().
map.put(key, node.asText());
} else {
map.put(key, mapKeys(child));
}
}
}
return map;
}
}
Trying to write a java class which convert JSON into Map by giving key. Sample method format and steps are below:
public Map<String, Map<String, String> convert(String jsonBody, String key){
Map<String, Map<String, String>> dataMap = new HashMap<String, Map<String, String>>();
Map<String, String> singleEntry = new HashMap<String, String>();
//Iterator<String> --get key from jsonBody
while(itr.hasNext()){
for(upto arary count){
singleEntry.put(jsonBody.getKey(i), jsonBody.getValue(i));
}
dataMap.put(itr.next(), singleEntry);
}
System.out.println(dataMap);
return data;
}
Sample JSON
[
{
"id": 146,
"Name": "John",
"LastName": "Mack",
},
{
"id": 148,
"Name": "Sam",
"LastName": "Rick",
}
]
Expected Output:
id -146, {id=146, Name = John, LastName =Mack}
id -148, {id=148, Name = Sam, LastName =Rick}
Please suggest best API and correct approach. Thanks in Advance.
See here for how to convert a json node to a Map.
See here about how to convert the json array to a map.
I have a service from where I get a json string response like as shown below
{
"id": "123",
"name": "John"
}
I consume the rest call using HttpClient and converts the json string to Map<String, String> like as shown below.
String url= "http://www.mocky.io/v2/5979c2f5110000f4029edc93";
HttpClient client = HttpClientBuilder.create().build();
HttpGet httpGet = new HttpGet(url);
httpGet.setHeader("Content-Type", "application/json");
HttpResponse httpresponse = client.execute(httpGet);
String response = EntityUtils.toString(httpresponse.getEntity());
ObjectMapper mapper = new ObjectMapper();
Map<String, String> map = mapper.readValue(response, new TypeReference<Map<String, String>>(){});
The conversion from json string to HashMap is working fine, but actually my requirement was sometimes there can be some nested json within the main json, for example in the below json I am having an additional address key which is again a nested json having city and town details.
{
"id": "123",
"name": "John",
"address": {
"city": "Chennai",
"town": "Guindy"
}
}
If any nested json comes I need the make the json like as shown below
{
"id": "123",
"name": "John",
"address.city": "Chennai",
"address.town": "Guindy"
}
Currently I am using jackson library, but open to any other library which will give me this feature out of box
Can anyone help me by giving some suggestion on this.
Here is a recursive method that will flatten a nested Map with any depth to the desired dot notation. You can pass it to Jackson's ObjectMapper to get the desired json output:
#SuppressWarnings("unchecked")
public static Map<String, String> flatMap(String parentKey, Map<String, Object> nestedMap)
{
Map<String, String> flatMap = new HashMap<>();
String prefixKey = parentKey != null ? parentKey + "." : "";
for (Map.Entry<String, Object> entry : nestedMap.entrySet()) {
if (entry.getValue() instanceof String) {
flatMap.put(prefixKey + entry.getKey(), (String)entry.getValue());
}
if (entry.getValue() instanceof Map) {
flatMap.putAll(flatMap(prefixKey + entry.getKey(), (Map<String, Object>)entry.getValue()));
}
}
return flatMap;
}
Usage:
mapper.writeValue(System.out, flatMap(null, nestedMap));
I'm trying to send API call using json-simple 1.1.1 and I save fields and values as a HashMap. I should send those parameters:
{ api_key : string,
product_id : string,
name : string,
tax_rates : array }
Here is a HashMap example:
HashMap<String,Object> arg = new HashMap<String, Object>();
arg.put("product_id","42");
arg.put("name", "EKOS");
arg.put("tax_rates", taxarray);
I saved taxarray as a HashMap as well:
HashMap<String, Object> taxarray = new HashMap<String, Object>();
taxarray.put("name","EKOS");
taxarray.put("type", "type_value_fixed");
taxarray.put("value", "56");
But when I execute an API call it reurns an error: Parameter 'tax_rates' is not valid. The required type of parameter is an array.
I had been trying to save taxarray HashMap as JSONArray as well. Could you please help me with this?
An additional question: how can I save 2 or more taxrates within one "tax_rates"? Here is an example:
HashMap<String,Object> arg = new HashMap<String, Object>();
arg.put("product_id","42");
arg.put("name", "EKOS");
arg.put("tax_rates", array [
taxarray1[],
taxarray2[]
]);
You should have something like this - Tax class:
public class Tax {
String name;
String type;
Integer[] values;
public Tax(String name, String type, Integer[] values) {
this.name = name;
this.type = type;
this.values = values;
}
}
And then use an array of objects of Tax class instead of HashMap for tax_rates : array.
This code using google json:
Map<String, Object> arg = new HashMap<String, Object>();
arg.put("product_id", "42");
arg.put("name", "EKOS");
arg.put("tax_rates",
new Tax[] { new Tax("EKOS", "type_value_fixed", new Integer[] { 1, 2, 3 }),
new Tax("ABC", "type_value_fixed", new Integer[] { 4, 5 }),
new Tax("DEF", "type_value_fixed", new Integer[] { 6, 7}) });
Gson gson = new Gson();
System.out.println(gson.toJson(arg));
Will give you such json:
{
"product_id": "42",
"name": "EKOS",
"tax_rates": [
{
"name": "EKOS",
"type": "type_value_fixed",
"values": [
1,
2,
3
]
},
{
"name": "ABC",
"type": "type_value_fixed",
"values": [
4,
5
]
},
{
"name": "DEF",
"type": "type_value_fixed",
"values": [
6,
7
]
}
]
}
tax_rates has to be an array, so do this:
List<Double> taxRates = new ArrayList<Double>();
taxRates.add(19);
taxRates.add(17.5);
Map<String,Object> arg = new HashMap<String, Object>();
arg.put("product_id","42");
arg.put("name", "EKOS");
arg.put("tax_rates", taxRates);