Following is my code can it be optimized for java 8 and can it be more efficient?
public String LanguageString(Set<Locale> languageSet) throws Exception {
JSONObject json = new JSONObject();
JSONObject tempj = new JSONObject();
JSONArray jArr = new JSONArray();
try {
for (Locale locale : languageSet) {
if (locale != null) {
tempj = new JSONObject();
tempj.put("lcode", locale.toLanguageTag());
tempj.put("ldisplay", locale.getDisplayName());
jArr.put(tempj);
}
}
json.put("root", jArr);
} catch (JSONException e) {
//
}
return json.toString();
}
If you want to use Java 8 and Stream API you can use stream, map and reduce to create your final JSONObject, e.g.
public static String languageStringUsingStream(Set<Locale> locales) {
return new JSONObject()
.put("root", locales.stream()
.map(locale -> new JSONObject()
.put("lcode", locale.toLanguageTag())
.put("ldisplay", locale.getDisplayName(Locale.ENGLISH))
)
.reduce(new JSONArray(), JSONArray::put, (a, b) -> a))
.toString();
}
Here you can find a complete example:
https://gist.github.com/wololock/27bd296fc894f6f4594f997057218fb3
Related
I am trying to build query dynamically from json object using StringBuilder and Iterator.
method:
public static void main(String[] args) {
//JSONArray jsonArray = array of json
//for(int i=0;i<jsonArray.length();i++){
//JSONObject jsonObject=jsonArray.get(i);
//for sample json
JSONObject jsonObject=new JSONObject("{\"SchemaId\":\"186f134a-e65c-4e2d-92c6-04afe6951dd6\",\"SchemaName\":\"CIR\",\"Schema\":\"{}\",\"Parent\":null,\"Application\":\"CA\",\"ModifiedDateTime\":\"2020-08-31T04:21:46.403\",\"Version\":\"3\",\"PageType\":\"Line\",\"favorite\":false,\"CategoryType\":\"bits\",\"IsDeleted\":true}");
createPreparedStmtQuery(jsonObject,"mytable");
//}
}
public static String createPreparedStmtQuery(JSONObject record,String tableName) throws JSONException {
record = modifyRecord(record);
Iterator<String> keys = record.keys();
StringBuilder builder = new StringBuilder();
builder.append("insert or replace into ");
builder.append(tableName);
builder.append(" (");
while(keys.hasNext()){
builder.append(keys.next()).append(",");
}
builder.setLength(builder.length() - 1);
builder.append(") values(");
keys = record.keys();
JSArray valuesArray = new JSArray();
while(keys.hasNext()){
String key = keys.next();
if( record.get(key) != null && record.get(key) instanceof String) {
}
builder.append("?").append(",");
valuesArray.put(record.get(key));
}
builder.deleteCharAt(builder.length() - 1);
builder.append(");");
JSONObject ret = new JSONObject();
ret.put("query",builder.toString());
ret.put("values",valuesArray);
return ret.toString();
}
private static JSONObject modifyRecord(JSONObject record) throws JSONException {
if (record.has("ValidFrom")) {
record.remove("ValidFrom");
}
if (record.has("ValidTo")) {
record.remove("ValidTo");
}
Iterator<String> keys = record.keys();
while(keys.hasNext()){
String key = keys.next();
if (record.get(key) instanceof JSONObject || record.get(key) instanceof List) {
record.put(key,((JSObject)record.get(key)).toString());
}
}
return record;
}
And an Error receiving like this:
Caused by: java.lang.StackOverflowError: stack size 1040KB at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:649)
Is there any issue in the above methods?How to solve it?
Thanks.
You could try to increase the stack size of your JVM. In your case, the size seems to be 1040KB. You can set it to another value (e.g. 48 MB) like this:
java -Xss48m
For more details and examples see https://www.baeldung.com/jvm-configure-stack-sizes or the official reference https://www.oracle.com/java/technologies/javase/vmoptions-jsp.html
So I'm kind of stuck. I'm experiencing with JSon and I'm trying to get all the total_price of different orders from a JSON file. I can read the file, but I'm having issue getting that specific information then sum it all up.
Here's the code I have so far.
public static void main(String[] args) {
JSONParser parser = new JSONParser();
try {
Object obj = parser.parse(new FileReader(
"/orders.json"));
JSONObject jsonObject = (JSONObject) obj;
JSONArray orderList = (JSONArray) jsonObject.get("orders");
System.out.println("\norders");
Iterator<String> iterator = orderList.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
obj = parser.parse(sCurrentLine);
JSONArray jsonArray = (JSONArray) obj;
for(obj : jsonArray){
JSONObject jsonObject = (JSONObject)obj;
JSONObject realTitle = (JSONObject)jsonObject.get("0");
String name = (String) realTitle.get("title");
}
} catch (Exception e) {
e.printStackTrace();
}
}
For the JSON file:
{
"orders":[
{
"id":4251070723,
"email":"heathcote_amya#gmail.com",
"closed_at":null,
"created_at":"2016-12-05T23:16:40-05:00",
"updated_at":"2016-12-05T23:16:40-05:00",
"number":137,
"note":null,
"token":"c460f260f4f38b8a2b1f78e6efd0140e",
"gateway":"",
"test":false,
"total_price":"179.04",
"default":true
},
{
"id":4251070787,
"email":"napoleon.batz#gmail.com",
"closed_at":null,
"created_at":"2016-12-05T23:16:40-05:00",
"updated_at":"2016-12-05T23:16:41-05:00",
"number":138,
"note":null,
"token":"54c4f1735cfec8f98ad16ae5e9a161cd",
"gateway":"",
"test":false,
"total_price":"14.62"
}
]
}
The error I get is for(obj : jsonArray) is causing me issue, but honestly, I don't think I'm even on the right path.
Thanks a lot for your help in advance!
Your code has obvious compile time errors. With in the for loop, you are again trying to do a get(0), which is incorrect.
I have refined the code.
Try this. Its giving proper result as below
The price data of each order --{4251070723=179.04, 4251070787=14.62}.
The total Price of all order --193.66
public static void main(String[] args) {
JSONParser parser = new JSONParser();
Map<String, String> priceData = new HashMap<>();
BigDecimal totalPrice = BigDecimal.ZERO;
String orderId = null;
String orderPrice = null;
try {
String sCurrentLine = null;
Object obj = parser.parse(new FileReader(
"orders.json"));
JSONObject jsonObject = (JSONObject) obj;
JSONArray orderList = (JSONArray)(jsonObject.get("orders"));
System.out.println("Complete order list --"+orderList.toString());
for(Object singleOrder : orderList) {
JSONObject singleArrayData = (JSONObject) singleOrder;
orderId = singleArrayData.get("id").toString();
orderPrice = singleArrayData.get("total_price").toString();
priceData.put(orderId, orderPrice);
totalPrice = totalPrice.add(new BigDecimal(orderPrice));
}
System.out.println("The price data of each order --"+priceData.toString());
System.out.println("The total Price of all order --"+totalPrice);
} catch (Exception e) {
e.printStackTrace();
}
}
I was trying to get an JSONObject from a HTTP response.
try
{
GetMethod postMethod = new GetMethod();
postMethod.setURI(new URI(url, true));
postMethod.setRequestHeader("Accept", "application/json");
httpClient.executeMethod(postMethod);
String resp=postMethod.getResponseBodyAsString();
org.json.JSONTokener tokener = new org.json.JSONTokener(resp);
finalResult = new org.json.JSONArray(tokener);
return finalResult;
}
But I got a runtime warning as
Going to buffer response body of large or unknown size. Using getResponseBodyAsStream instead is recommended.
Should I get the response as stream as suggested by the JVM ? If so, how could I parse the JSON from it ?
Has your server been set up to inform clients how big its responses are? If not, your server is streaming the data, and it's technically impossible to tell how much buffer space is required to deal with the response, warranting a warning that something potentially dangerous is going on.
if you want to send jsonObjects from server suppose (tomcat server)
For server side-
creating jsonobjects-
I have Called toJson() for creating jsonobjects this is the implementation-
final JSONObject arr = new JSONObject();
for (int i = 0; i < contactStatus.size(); i++) {
ContactStatus contactObject = contactStatus.get(i);
try {
arr.put(String.valueOf(i), toJson(value1, value2,, value3));
} catch (JSONException e) {
catch block e.printStackTrace();
}
}
//Here we serialize the stream to a String.
final String output = arr.toString();
response.setContentLength(output.length());
out.print(output);//out is object of servlet output stream.
public static Object toJsonForContact(String value1, boolean value2, double value3) throws JSONException {
JSONObject contactObject = new JSONObject();
contactObject.put("id", id);
contactObject.put("status", value1);
contactObject.put("distance", value2);
contactObject.put("relation", value3);
return contactObject;
}
so your jsonobjects are ready for sending we write these objects to ServletoutputStream.
in client side-
while ((ReadResponses = in.readLine()) != null) {
Constants.Response_From_server = ReadResponses;
if (Constants.Response_From_server.startsWith("{")) {
ListOfContactStatus = new ArrayList<ContactStatus>();
ContactStatus contactStatusObject;
try {
JSONObject json = new JSONObject(Constants.Response_From_server);
for (int i = 0; i < json.length(); i++) {
contactStatusObject = new ContactStatus();
JSONObject json1 = json.getJSONObject(String.valueOf(i));
System.out.println("" + json1.getString("id"));
System.out.println("" + json1.getBoolean("status"));
System.out.println("" + json1.getDouble("distance"));
contactStatusObject.setId(json1.getString("id"));
contactStatusObject.setStatus(json1.getBoolean("status"));
contactStatusObject.setDistance((float) json1.getDouble("distance"));
ListOfContactStatus.add(contactStatusObject);
System.out.println("HTTPTransport:sendMessage Size of ListOfContactStatus" + ListOfContactStatus.size());
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
You can easily generate JSonObject usin Java EE 7. The sample code.
JsonReader reader = Json.createReader(new URI(url, true));
JsonObject jsonObject=reader.readObject();
For details information go through to the link.
http://docs.oracle.com/javaee/7/tutorial/doc/jsonp003.htm#BABHAHIA
Is there a way to clone an instance of org.json.JSONObject without stringifying it and reparsing the result?
A shallow copy would be acceptable.
Easiest (and incredibly slow and inefficient) way to do it
JSONObject clone = new JSONObject(original.toString());
Use the public JSONObject(JSONObject jo, java.lang.String[] names) constructor and the public static java.lang.String[] getNames(JSONObject jo) method.
JSONObject copy = new JSONObject(original, JSONObject.getNames(original));
Cause $JSONObject.getNames(original) not accessible in android,
you can do it with:
public JSONObject shallowCopy(JSONObject original) {
JSONObject copy = new JSONObject();
for ( Iterator<String> iterator = original.keys(); iterator.hasNext(); ) {
String key = iterator.next();
JSONObject value = original.optJSONObject(key);
try {
copy.put(key, value);
} catch ( JSONException e ) {
//TODO process exception
}
}
return copy;
}
But remember it is not deep copy.
For Android developers, the simplest solution without using .getNames is:
JSONObject copy = new JSONObject();
for (Object key : original.keySet()) {
Object value = original.get(key);
copy.put(key, value);
}
Note: This is a only a shallow copy
the fastest + minimal way I found is this. it does deep copy.
JSONObject clone= new JSONObject(original.toMap());
I know the asker said
A shallow copy would be acceptable.
but I think that does not rule out if the solution will do deep copy.
Update: the toMap() function is not available in Android. but the org.json library available on maven under groupId org.json has it: https://search.maven.org/artifact/org.json/json/20210307/bundle
Couldn't find an existing deep clone method for com.google.gwt.json.client.JSONObject but the implementation should be few lines of code, something like:
public static JSONValue deepClone(JSONValue jsonValue){
JSONString string = jsonValue.isString();
if (string != null){return new JSONString(string.stringValue());}
JSONBoolean aBoolean = jsonValue.isBoolean();
if (aBoolean != null){return JSONBoolean.getInstance(aBoolean.booleanValue());}
JSONNull aNull = jsonValue.isNull();
if (aNull != null){return JSONNull.getInstance();}
JSONNumber number = jsonValue.isNumber();
if (number!=null){return new JSONNumber(number.doubleValue());}
JSONObject jsonObject = jsonValue.isObject();
if (jsonObject!=null){
JSONObject clonedObject = new JSONObject();
for (String key : jsonObject.keySet()){
clonedObject.put(key, deepClone(jsonObject.get(key)));
}
return clonedObject;
}
JSONArray array = jsonValue.isArray();
if (array != null){
JSONArray clonedArray = new JSONArray();
for (int i=0 ; i < array.size() ; ++i){
clonedArray.set(i, deepClone(array.get(i)));
}
return clonedArray;
}
throw new IllegalStateException();
}
*Note:*I haven't tested it yet!
In case anyone comes here looking for a deep clone for org.google.gson, since they don't expose their deepClone() method this is what I came up with...
public static JsonElement deepClone(JsonElement el){
if (el.isJsonPrimitive() || el.isJsonNull())
return el;
if (el.isJsonArray()) {
JsonArray array = new JsonArray();
for(JsonElement arrayEl: el.getAsJsonArray())
array.add(deepClone(arrayEl));
return array;
}
if(el.isJsonObject()) {
JsonObject obj = new JsonObject();
for (Map.Entry<String, JsonElement> entry : el.getAsJsonObject().entrySet()) {
obj.add(entry.getKey(), deepClone(entry.getValue()));
}
return obj;
}
throw new IllegalArgumentException("JsonElement type " + el.getClass().getName());
}
And here are a few methods to merge two JsonObject's
public static JsonObject merge(String overrideJson, JsonObject defaultObj) {
return mergeInto((JsonObject)new JsonParser().parse(overrideJson), defaultObj);
}
public static JsonObject merge(JsonObject overrideObj, JsonObject defaultObj) {
return mergeOverride((JsonObject)deepClone(defaultObj), overrideObj);
}
public static JsonObject mergeOverride(JsonObject targetObj, JsonObject overrideObj) {
for (Map.Entry<String, JsonElement> entry : overrideObj.entrySet())
targetObj.add(entry.getKey(), deepClone(entry.getValue()));
return targetObj;
}
public static JsonObject mergeInto(JsonObject targetObj, JsonObject defaultObj) {
for (Map.Entry<String, JsonElement> entry : defaultObj.entrySet()) {
if (targetObj.has(entry.getKey()) == false)
targetObj.add(entry.getKey(), deepClone(entry.getValue()));
}
return targetObj;
}
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
Map<String, Object> map = new HashMap<String, Object>();
map.put("abc", "123456");
map.put("def", "hmm");
list.add(map);
JSONObject json = new JSONObject(list);
try {
System.err.println(json.toString(2));
} catch (JSONException e) {
e.printStackTrace();
}
What's wrong with this code?
The output is:
{"empty": false}
public String listmap_to_json_string(List<Map<String, Object>> list)
{
JSONArray json_arr=new JSONArray();
for (Map<String, Object> map : list) {
JSONObject json_obj=new JSONObject();
for (Map.Entry<String, Object> entry : map.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
try {
json_obj.put(key,value);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
json_arr.put(json_obj);
}
return json_arr.toString();
}
alright, try this~ This worked for me :D
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
Map<String, Object> map = new HashMap<String, Object>();
map.put("abc", "123456");
map.put("def", "hmm");
list.add(map);
// it's wrong JSONObject json = new JSONObject(list);
// if u use list to add data u must be use JSONArray
JSONArray json = JSONArray.fromObject(list);
try {
System.err.println(json.toString(2));
} catch (JSONException e) {
e.printStackTrace();
}
You need to end up with a JSONArray (corresponding to the List) of JSONObjects (the Map).
Try declaring the json variable as a JSONArray instead of a JSONObject (I believe the JSONArray constructor will do the right thing).
Also: you could consider using one of other parsers from json.org's list: most of them allow your Json "objects" and "arrays" to map natively to java.util.Maps and java.util.Lists; or in some cases to real Java objects too.
My recommendation would be Jackson, http://jackson.codehaus.org/Tutorial
which allows for mapping to List/Map/Integer/String/Boolean/null, as well as to real Beans/POJOs. Just give it the type and it maps data to you, or writes Java objects as Json.
Others like "json-tools" from berlios, or google-gson also expose similar functionality.
You have a map nested inside a list. you are trying to call the Map without ever iterating through the list first. JSON sometimes feels like magic but in fact it is not.
I'll post some code in a moment.
It would be more consistent with JSON to make a Map of Maps instead of a List of Maps.
JSONObject json = new JSONObject(list);
Iterator<?> it = json.keys();
while (keyed.hasNext()) {
String x = (String) it.next();
JSONObject jo2 = new JSONObject(jo.optString(x));
}
This worked for me:
List<JSONObject> jsonCategories = new ArrayList<JSONObject>();
JSONObject jsonCategory = null;
for (ICategory category : categories) {
jsonCategory = new JSONObject();
jsonCategory.put("categoryID", category.getCategoryID());
jsonCategory.put("desc", category.getDesc());
jsonCategories.add(jsonCategory);
}
try {
PrintWriter out = response.getWriter();
response.setContentType("text/xml");
response.setHeader("Cache-Control", "no-cache");
_log.info(jsonCategories.toString());
out.write(jsonCategories.toString());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
If you are using org.json.simple.JSONArray
(https://mvnrepository.com/artifact/com.googlecode.json-simple/json-simple/1.1.1)
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
Map<String, Object> map = new HashMap<String, Object>();
map.put("abc", "123456");
map.put("def", "hmm");
list.add(map);
JSONArray jsonArray = new JSONArray();
jsonArray.addAll(listOfMaps);
You can do it using both:
JSONArray directly as,
String toJson(Collection<Map<String, Object>> list)
{
return new JSONArray(list).toString();
}
Or by iterating the list with Java8 (like #ShadowJohn solution):
String toJson(Collection<Map<String, Object>> list)
{
return new JSONArray(
list.stream()
.map((map) -> new JSONObject(map))
.collect(Collectors.toList()))
.toString();
}