#sinfonier BOLT - Adding a jarray object to output - java

If I make
JSONArray array = new JSONArray();
[...]
this.addField("array", array);
it generates:
{..., "array":"[\"x\", \"y\"]" }
When it should be:
{..., "array": ["x", "y"] }
The sinfonier probably calls toString on the jarray object. I think it should create a full json and then call toString on the full json.
Is there any other way to do this?
(this is a sinfonier specific question, sorry, but no sinfonier tag available yet)

So, I participate in sinfonier Hackathon on Campus Party Recife, if you need create a array you need create json objects before and add them in array, like this:
import org.json.JSONArray;
...
List aryLst = new ArrayList();
aryLst.add("x");
aryLst.add("y");
JSONArray list = new JSONArray(aryLst);
Sinfonier use org.json package to manipulate json objects.
But if your bolt gets json from a truple and you save a value of a json in a field you can get this value directly from truple and save. Or you can use json fields normaly like a field in other bolt or drain.

In order to create an array list and add it into a field to your current tuple/map it's necessary to make an ArrayList> instance.
Firts import com.google.gson libraries:
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
Then add every item from your source array to new ArrayList instance:
JSONArray originalJsonArray = new JSONArray(json);
ArrayList<Map<String, Object>> newArrayList = new ArrayList<Map<String, Object>>();
if (originalJsonArray != null) {
for (int i=0;i<originalJsonArray.length();i++){
Map<String, Object> fieldValueItem = new Gson().fromJson(originalJsonArray.get(i).toString(), new TypeToken<HashMap<String, Object>>() {}.getType());
newArrayList.add(fieldValueItem);
}
}
Finally add your new array:
this.addField("newarraylist",newArrayList);
this.addField("newarraylistlength",newArrayList.length());

Related

Why can't read a .json?

I want to read a .json using library json-simple, my json file is:
{
"Subjects": {
"subject1": "MIS",
"subject2": "DBMS",
"subject3": "UML"
}
}
And my code is:
import java.io.*;
import java.util.*;
import org.json.simple.*;
import org.json.simple.parser.*;
public class JSONReadFromTheFileTest {
public static void main(String[] args) {
JSONParser parser = new JSONParser();
try{
Object obj = parser.parse(new FileReader("/Users/User/Desktop/course.json"));
JSONObject jsonObject = (JSONObject)obj;
JSONArray subjects = (JSONArray)jsonObject.get("Subjects");
Iterator iterator = subjects.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}catch(Exception e){
e.printStackTrace();
}
}
}
I would like to get in console:
subject1: MIS
subject2: DBMS
subject3: UML
But instead of that, I just get the next error:
java.lang.ClassCastException: org.json.simple.JSONObject cannot be cast to org.json.simple.JSONArray
at project.Main(Main.java:11)
But I searched in internet, and I found that if I change sintaxys of the .json in the next way:
{
"Subjects": [
"subject1: MIS",
"subject2: DBMS",
"subject3: UML"
]
}
I get in console what I want:
subject1: MIS
subject2: DBMS
subject3: UML
And you may think my problem is solved, but not yet, because I want to read the json file in the first way.
I hope someone can help me. Thanks in advance.
The first example shows a Subjects key containing a single object with several properties (subject1, subject2, etc).
Consider those properties like the member variables of a class.
In order to let you better understand if the class is Person those variables could be name and surname.
What you try to achieve in your code is extracting a JSONArray from the JSON you are providing.
Going back to the example for Person the array could be - sorry for the silly example - an Array containing phone numbers.
So what you are expecting is that one of the member properties of the class is an array.
This is not possible in the first example because the first example does not contain a json array.
This line extracts the whole json object:
JSONObject jsonObject = (JSONObject)obj;
This one tries to get an array out but no array is there in the first example:
JSONArray subjects = (JSONArray)jsonObject.get("Subjects");
Square brackets represent an array, which you've casted the getter into.
The second json shown is more correct for the code you've written, however, arrays cannot hold key-value pairs, so that's why you've made second JSON have an array of strings
To parse the first file, you'd need to start with
JSONObject subjects = (JSONObject)jsonObject.get("Subjects")
If you have full control over the file, I'd suggest just storing ["MIS", "DBMS", "UML"] then write a simple loop
for (int i = 0; i < jsonArray.length; i++) {
System.out.printf("subject%d: %s%n", i+1, jsonArray.get(i));
}
To make your code work with your json, you should not use JSONArray for "Subjects" but instead JSONObject. The reason is that [ and ] indicates beginning and ending of array element in json which is represented by JSONArray. If you have { and } element then its object represented by JSONObject. zz So replace this:
JSONArray subjects = (JSONArray)jsonObject.get("Subjects");
Iterator iterator = subjects.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
with following (I have not compiled it):
JSONObject subjects = (JSONObject)jsonObject.get("Subjects");
for(Iterator iterator = subjects.keySet().iterator(); iterator.hasNext();) {
String key = (String) iterator.next();
System.out.println(key + ": " + subjects.get(key));
}
As others mentioned you should replace JSONArray with JSONObject in your code. But I would suggest to switch to different JSON library all together. I would recommend to use Json-Jackson library. Also, there is another library that provides a wrapper over Json-Jackson library. It has JsonUtils class that can simply parse your JSON in one line. Just read first your Json from file into a String jsonString and do this.
Map<String, Object> myMap = JsonUtils.readObjectFromJsonString(jsonString, Map.class);
You will get a Map with one key "Subjects" that will have a value of a Map with your 3 keys and values:
subject1: MIS
subject2: DBMS
subject3: UML
Here is the JavaDoc for the JsonUtils class. The library could be found as Maven artifact and on Github (including source code and Javadoc).

How can I can save HashMap in my Android app?

I have member variable HashMap<Integer, HashMap<String[], Integer>> in some activity in my Android app. The HashMap supposed to survive from user launch app for the first time till the app will be deleted. I can't use shared preferences because there aren't such put method. I know about room database but I don't really want to use that in this case. Please, tell me which options are there to save HashMap and store it in memory.
You can try to serialize HashMap to string.
Import this library in your build.gradle file first.
implementation 'com.google.code.gson:gson:2.8.6'
To have serialize data you can follow this code:
public static String hashToString (HashMap<Integer, HashMap<String[], Integer>> hashMap) {
if (hashMap == null) return null;
Gson gson = new Gson();
//import java.lang.reflect.Type;
//import com.google.gson.reflect.TypeToken;
Type type = new TypeToken<HashMap<Integer, HashMap<String[], Integer>>(){}.getType();
return gson.toJson(hashMap, type);
}
Now you can convert any object to string you can use this method..
To get back object from string:
public static HashMap<Integer, HashMap<String[], Integer>> stringToHash (String json) {
if (json == null) return null;
Gson gson = new Gson();
//import java.lang.reflect.Type;
//import com.google.gson.reflect.TypeToken;
Type type = new TypeToken<HashMap<Integer, HashMap<String[], Integer>>(){}.getType();
return gson.fromJson(json, type);
}
PaperDB library is best for store anything believe i use paperDB to store HashMap,POJO Class Object, Array and so on... and it just serializes the any object store in local storage.
Github Link Of PaperDB : https://github.com/pilgr/Paper
In Above Link you can learn about how to use this!

Using javax/json, how can I add elements to an existing JsonArray?

I read a JSON array from a file but I'd like to add additional entries into the array. How would I go about doing this using the javax.json library?
private String getJson(FileInputStream fis) throws IOException {
JsonReader jsonReader = Json.createReader(fis);
// Place where I'd like to get more entries.
String temp = jsonReader.readArray().toString();
jsonReader.close();
fis.close();
return temp;
}
Preview of the JSON format of the file:
[
{"imgOne": "test2.png", "imgTwo": "test1.png", "score": 123123.1},
{"imgOne": "test2.png", "imgTwo": "test1.png", "score": 1234533.1}
]
The short answer is that you can't. JsonArray (and the other value types) is meant to be immutable. The javadoc states
JsonArray represents an immutable JSON array (an ordered sequence of
zero or more values). It also provides an unmodifiable list view of
the values in the array.
The long answer is to create a new JsonArray object by copying over the values from the old one and whatever new values you need.
For example
// Place where I'd like to get more entries.
JsonArray oldArray = jsonReader.readArray();
// new array builder
JsonArrayBuilder builder = Json.createArrayBuilder();
// copy over old values
for (JsonValue value : oldArray) {
builder.add(value);
}
// add new values
builder.add("new string value");
// done
JsonArray newArray = builder.build();

Create merged JSON with GSON

I've found tons of examples of using GSON to convert either an single object, or a list of that single object, to its respective JSON. Quite easy to do. Even if the object has objects as its properties, this still is trivial.
But let's say I have 5 objects of interest (names, companies, colors, numbers, candy) and they have no relationship to each other at all. So I make my database calls, and now have 5 lists full of all of the above in my code.
Now, how could I put these lists into a JSON Array whose parent name is "items" and contains all of the above as children beneath it? So one parent "items", with 5 children (each child is a sibling of each other).
What is the appropriate way using GSON (or not??) to construct such a tree or structure?
I noticed there is a lot in GSON such as JSONArray and such, but wasn't able to figure it out.
Thanks so much!
Yes, you can. You have to build your own serializer first. For instance:
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public static String toJson(List<Item> items){
try{
JSONObject jsonObj = new JSONObject();
JSONArray jsonArr = new JSONArray();
for(Item i : items){
JSONObject itemObj = new JSONObject();
itemObj.put("names", i.getName());
itemObj.put("companies", i.getCompanies());
itemObj.put("colors", i.getColors());
itemObj.put("numbers", i.getNumbers());
itemObj.put("candy", i.getCandy());
jsonArr.put(itemObj);
}
jsonObj.put("items", jsonArr);
return jsonObj.toString();
} catch(JSONException ex){
ex.printStackTrace();
}
return null;
}
Depending on what the fields are, you can make a model class and set the objects from database. The use Gson and form your Json string using jsonFrom.
Eg.
public class Items{
ArrayList<String> names;
String candy;
//nested custom class if necessary
ArrayList<Companies> companies;
//other fields here
//getter setter
}
Now set the values for objects of Items.
Then:
Gson gson = new Gson();
String json = gson.toJson(modelClassObject);
If i got your requirement right, json is the String you need.
To merge JSONs you need to define some conventions of merging. If "Overlay" strategy (replace or add) conforms you, you can find a helpful JSON Merging Library in this answer.

Java JSON object to read a list value

I have a JSON response something like this:
{
"id_list":["123", "456", "789"],
...
}
I was wondering what I should do if I want use the JSONObject to read such a id list and to return a List<String> of the ids for example. I did not see there's any method in JSONObject can do such thing (ref: http://www.json.org/javadoc/org/json/JSONObject.html). The most possible one might be the JSONArray, but I don't know if I use JSONArray and turn every value in the list to be an JSONObject, how can I read them without keys.
Thank you
You can iterate through the JSONArray and store each value to the list, and return that.
JSONObject jo = new JSONObject(jsonString); //
JSONArray ja = jo.getJSONArray("id_list"); // get the JSONArray
List<String> keys = new ArrayList<>();
for(int i=0;i<ja.length();i++){
keys.add(ja.getString(i)); // iterate the JSONArray and extract the keys
}
return keys; // return the list

Categories

Resources