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);
Related
I wanted to serialize a class who contains a HashMap and that hHashHap has a class key. but it goes wrong.
public class Buyer {
private long wallet;
private HashMap<Discount, Integer> discountCodes;
}
when I use toJson method
"discountCodes":{"model.Discount#18769467":1,"model.Discount#1cf4f579":2}
it serialized like this so in deserializing cause ERROR
Exception in thread "main" com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 34 path $[0].discountCodes.
I mean how to convert an object of Buyer to json not converting HashMap
Serialize HashMap containing generic types to JSON
HashMap<Integer, Employee> employeeMap = new HashMap<>();
employeeMap.put(1, new Employee(1l, "Alex", LocalDate.of(1990, 01, 01)));
employeeMap.put(2, new Employee(2l, "Bob", LocalDate.of(1990, 02, 01)));
//Deep clone
Gson gson = new Gson();
String jsonString = gson.toJson(employeeMap);
Generated json:
{
"1": {
"id": 1,
"name": "Alex",
"dob": {
"year": 1990,
"month": 1,
"day": 1
}
},
"2": {
"id": 2,
"name": "Bob",
"dob": {
"year": 1990,
"month": 2,
"day": 1
}
}
}
Convert JSON to HashMap containing custom objects
HashMap<Integer, Employee> employeeMap = new HashMap<>();
employeeMap.put(1, new Employee(1l, "Alex", LocalDate.of(1990, 01, 01)));
employeeMap.put(2, new Employee(2l, "Bob", LocalDate.of(1990, 02, 01)));
//Deep clone
Gson gson = new Gson();
String jsonString = gson.toJson(employeeMap);
Type type = new TypeToken<HashMap<Integer, Employee>>(){}.getType();
HashMap<Integer, Employee> clonedMap = gson.fromJson(jsonString, type);
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 the following JSON data:
[
{
"id": 4,
"siteName": "site1",
"addressLine1": "address1",
"addressLine2": "address2",
"town": "town1",
"postcode": "postcode1",
"contactName": "name1",
"contactNumber": "number1",
"contactEmail": "email1"
},
{
"id": 5,
"siteName": "site2",
"addressLine1": "address1",
"addressLine2": "address2",
"town": "town1",
"postcode": "postcode1",
"contactName": "name1",
"contactNumber": "number1",
"contactEmail": "email1"
},
]
I'm parsing the data but it simply outputs one long string. I'd like to access each element within each object.
UPDATE: I'm outputting the individual elements, but for some reason the 'id' property is considered a double?
Map<String,Object> jsonArr = new JSONParser().parseJSON(new InputStreamReader(new ByteArrayInputStream(r.getResponseData()), "UTF-8"));
java.util.List<Map<String, Object>> content = (java.util.List<Map<String, Object>>)jsonArr.get("root");
for(Map<String, Object> obj : content) {
Log.p((int)obj.get("id"));
Log.p((String)obj.get("siteName"));
Log.p((String)obj.get("addressLine1"));
Log.p((String)obj.get("addressLine2"));
Log.p((String)obj.get("town"));
Log.p((String)obj.get("postcode"));
Log.p((String)obj.get("contactName"));
Log.p((String)obj.get("contactNumber"));
Log.p((String)obj.get("contactEmail"));
}
As you're using Codename One, parseJSON always returns a Map<String, Object>, but behaves differently when the root element is an array. In that case, the returned Map contains an object whose key is "root" which you then can iterate on to obtain the actual objects.
Map<String, Object> data = json.parseJSON(new InputStreamReader(
new ByteArrayInputStream(r.getResponseData()), "UTF-8"));
List<Map<String, Object>> content = (java.util.List<Map<String, Object>>)data.get("root");
for(Map<String, Object> obj : content) {
Log.p(obj.getValue().toString());
}
For further info see the documentation for the parseJSON method.
You are getting an array of objects as it stats with [ and ends with ]. You have to try like this.
JSONArray jsonArr = new JSONParser().parseJSON(new InputStreamReader(new ByteArrayInputStream(r.getResponseData()), "UTF-8"));
for (int i = 0; i < jsonArr.length(); i++) {
String siteName = jsonArr.getJSONObject(i).getString("siteName");
System.out.println(siteName);
}
I have a method that takes in a List<String> and List<Map<String, Object>>:
public List<Map<String, Object>> filterMethod() {
List<String> listId = this.getUserIds(); //includes only the user id's
List<Map<String, Object>> listUser = this.getUserDetails(); // includes user_id, user_name, and user_email
List<Map<String, Object>> filteredListUser = null;
return filteredListUser;
}
What I would like to be able to do, is compare these two and return a new List<Map<String, Object>>.
The comparison I'd like to do shown as an example:
Let's say:
List<String> listId =
[
"8000",
"8002",
"8004",
"8006",
"8010",
"8012",
"8014",
"8016",
"8018",
"8020",
"8022",
"8024"
]
List<Map<String, Object>> listUser =
[
{
"USER_ID": "8001",
"USER_NAME": "username1",
"USER_MAIL": "email1#foo.com"
},
{
"USER_ID": "8002",
"USER_NAME": "username2",
"USER_MAIL": "email2#foo.com"
},
{
"USER_ID": "8003",
"USER_NAME": "username3",
"USER_MAIL": "email3#foo.com"
},
{
"USER_ID": "8004",
"USER_NAME": "username4",
"USER_MAIL": "email4#foo.com"
},
{
"USER_ID": "8005",
"USER_NAME": "username5",
"USER_MAIL": "email5#foo.com"
},
{
"USER_ID": "8006",
"USER_NAME": "username6",
"USER_MAIL": "email6#foo.com"
},
{
"USER_ID": "8007",
"USER_NAME": "username7",
"USER_MAIL": "email7#foo.com"
}
]
I would like to return a new filtered List<Map<String, Object>>, that contains listUser rows where a listUser USER_ID is in listId (i.e:)
List<Map<String, Object>> filteredListUser =
[
{
"USER_ID": "8002",
"USER_NAME": "username2",
"USER_MAIL": "email2#foo.com"
},
{
"USER_ID": "8004",
"USER_NAME": "username4",
"USER_MAIL": "email4#foo.com"
},
{
"USER_ID": "8006",
"USER_NAME": "username6",
"USER_MAIL": "email6#foo.com"
}
]
The issue comes when I need to compare the user_id from listUser with listId in order to check if I need to add the row to filteredListUser.
I would know how to do this if this were simply two string arrays like so:
String[] a = {1, 2, 3, 4, 5, 6, 7};
String[] b = {2, 4, 6, 8, 10};
ArrayList<String> c = new ArrayList<String>();
for (int i = 0; i < a.length; i++) {
if (Arrays.asList(b).contains(a[i])) {
c.add(a[i]);
}
}
I think a for-loop would also be appropriate for the List comparisons, but I am unsure as to how I can compare the user_id in listUser with listId in List<Map<String, Object>> and List<String>.
As an attempt and pseudo-code perspective, what I am trying to accomplish is this:
public List<Map<String, Object>> filterMethod() {
List<String> listId = this.getUserIds(); //includes only the user id's
List<Map<String, Object>> listUser = this.getUserDetails(); // includes user_id, user_name, and user_email
List<Map<String, Object>> filteredListUser = null;
for (int i = 0; i < listUser.length; i++) {
if (listId.contains(listUser.USER_ID[i])) {
filteredListUser.add(listUser[i]);
}
}
return filteredListUser;
}
I'm not entirely sure where to go from here however - would appreciate any help!
Apologies if this is a really rudimentary question - I'm very new to programming. Thank you in advance!
I would iterate the List<Map<String, Object>> and check corresponding value to USER_ID is present in List<String> listId. below is the approach by using java-8 streams
List<Map<String, Object>> result = listUser.stream()
.filter(m-> listId.contains(m.get("USER_ID")))
.collect(Collectors.toList());
or By using simple for loop
List<Map<String, Object>> filteredListUser = new ArrayList<>();
for(Map<String, Object> m : listUser) {
if(listId.contains(m.get("USER_ID"))) {
filteredListUser.add(m);
}
}
You can also do it by using removeIf but this modifies the existing map
listUser.removeIf(m->!listId.contains(m.get("USER_ID")));
I have an issue with java 8 implementation regarding multiple aggregation of HashMap list , (preferred with "reduce" function , but not must)
I need to make multiple aggregation by key name - "service" with split("_")[0] as in Json below:
Suppose my data structure :
List<Map<String, Object>> payments = new ArrayList<>();
for(int i=0 ; ....i++){
Map<String, String> map = new HashMap<>();
map.put("service","IMAP_"+i);
map.put("storageValue",<some value>)
....
payments.add(map);
}
The Json:
{
"payments": [
{
"service": "IMAP_1",
"storageValue": 10,
"users": "10"
},
{
"service": IMAP_2,
"storageValue": 20,
"users": "1"
},
{
"storageValue": 200,
"service": "Office 365 Exchange_1",
"users": "15"
},
{
"storageValue": 200,
"service": "Office 365 Exchange_2",
"users": "10"
},
{
"storageValue": 50,
"service": "SalesForce_1",
"users": "100"
}
]
}
The result should be :
{
"payments": [
{
"service": "IMAP",
"storageValue": 30,
"users": "11"
},
{
"storageValue": 400,
"service": "Office 365 Exchange",
"users": "25"
},
{
"storageValue": 50,
"service": "SalesForce",
"users": "100"
}
]
}
should be something..
payments.stream().forEach(paymet -> {
paymet.entrySet().stream().map(....?...).reduce()...
);
Here's an incomplete suggestion that combines Collectors.groupingBy with Collectors.reducing.
Map<String,Optional<Map<String,Object>>> result =
payments.stream ().collect(Collectors.groupingBy (map -> map.get ("service").split ("_")[0],
Collectors.reducing ((m1,m2)-> {
Map<String,String> m = new HashMap<>();
m.put("service",m1.get("service")); // you may have to remove the _1 suffix
m.put("storageValue",(Integer)m1.get("storageValue")+(Integer)m2.get("storageValue"));
m.put("users",(Integer)m1.get("users")+(Integer)m2.get("users"));
return m;
})));
Note that since your Maps contain String values, it's a bit inconvenient to add the values of these Map as if they are numbers. You'll have to do some conversions from String to int and vice versa.
It might be helpful to convert each Map into an instance of some class having storage, users and storageValue properties. Then you can have a method that combines two such instances.
Try this one. it isn't elegance :).
first change service key's value to the new value
payments.stream()
.forEach(item -> item.put("service", item.get("service").split("_")[0]));
then
HashMap<String, HashMap> mapOfMaps = payments.stream()
.collect(Collectors.toMap(hashMap -> hashMap.get("service"),
hashMap -> (HashMap) hashMap,
YOURCLASS::merge, HashMap::new));
List<HashMap> result = new ArrayList<>(mapOfMaps.values());
and define a method to merge two maps like following:
private static HashMap<String, String> merge(HashMap<String, String> map1, HashMap<String, String> map2) {
if (map1.get("service").equals(map2.get("service"))) {
Long storageValue = Long.valueOf(map1.get("storageValue")) + Long.valueOf(map2.get("storageValue"));
map1.put("storageValue", storageValue.toString());
Long users = Long.valueOf(map1.get("users")) + Long.valueOf(map2.get("users"));
map1.put("users", users.toString());
}
return map1;
}