Parsing Multiple JSON Strings to Objects using json-simple - java

I have a socket server running, which will emit json strings for clients. I tried to use json-simple for parsing them. But, the problem I face is that, the server doesn't have any delimiter character to segregate json strings. So, my json-simple JSONParser throws ParseException.
As an alternate, I tried to use json-smart. But, in this case, the JSONParser returns only the first object and ignores rest of the string.
I'm new to this json parsing stuff. It would be great if people can direct me to correct way of handling json string streams.
Edit: - Adding JSON String and Sample Code
{"type":"response","id":"1","result":[true,0]}{"type":"response","id":"2","result":[true,1]}
Currently this method returns the single object when I use json-smart and null when json-simple is used.
public JSONObject getResponse(JSONObject request) {
String s = null;
Socket soc = null;
PrintWriter sout = null;
BufferedReader sin = null;
try {
soc = new Socket(InetAddress.getByName("127.0.0.1"), 9090);
sout = new PrintWriter(soc.getOutputStream());
sin = new BufferedReader(
new InputStreamReader(soc.getInputStream()));
sout.println(request.toJSONString());
sout.flush();
s = sin.readLine();
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
try {
sin.close();
sout.close();
soc.close();
} catch (Exception e) {
}
}
Object response = null;
try {
response = JSONValue.parseWithException(s.toString());
}catch (ParseException e){
e.printStackTrace();
}
return (JSONObject) response;
Thanks in advance,
Kaja

I have found a solution using Jackson. Here is the code that worked for me.
MappingJsonFactory factory = new MappingJsonFactory();
JsonParser parser = factory.createParser(soc.getInputStream());
JsonToken curToken = parser.nextToken();
if (curToken != JsonToken.START_OBJECT) {
System.err.println("Not in start object!, Exiting...");
return null;
}
while (runParser.get() == true) {
if (curToken == JsonToken.START_OBJECT) {
TreeNode node = parser.readValueAsTree();
System.out.println(node.getClass().getName());
System.out.println(node);
}
curToken = parser.nextToken();
}

Thanks Kaja Mohideen! It's working with a small change in while loop.
This code works perfectly. In my case input json is in file.
libs used : jackson-core, jackson-annotation and jackson-databind
MappingJsonFactory factory = new MappingJsonFactory();
JsonParser parser = null;
File file = new File("jsontest.txt");
try {
parser = factory.createParser(file);
JsonToken curToken = parser.nextToken();
if (curToken != JsonToken.START_OBJECT) {
System.err.println("Not in start object!, Exiting...");
}
while (parser.hasCurrentToken()) {
if (curToken == JsonToken.START_OBJECT) {
TreeNode node = parser.readValueAsTree();
System.out.println(node);
}
curToken = parser.nextToken();
}
} catch (JsonParseException e) {
e.printStackTrace();
}

Related

Jersey RESTful: How to populate DAO with a local json file?

this is my first time building a Jersey Restful web service.
The project is supposed to be a server that provides information about Reddit posts. For now, this information is stored in a large JSON file, and because it is not supposed to be manipulated, my idea is to store this information in the dao class in form of Post instances.
here is my projects' folder organisation: filesView
So my idea is to populate the dao class by reading the json file something like this:
public enum PostDao {
instance;
private Map<String, Post> posts = new HashMap<String, Post>();
private PostDao() {
//JSON parser object to parse read file
System.out.println("init");
JSONParser jsonParser = new JSONParser();
try {
FileReader reader = new FileReader("src/main/resources/data/posts.json");
//Read JSON file
Object obj = jsonParser.parse(reader);
JSONArray postsArr = (JSONArray) obj;
for (Object p : postsArr) {
JSONObject post = (JSONObject) p;
Post pobj = new Post(post.get("title"), post.get("author"));
posts.put(pobj.getId(), pobj);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}
}
public Map<String, Post> getModel() {
return posts;
}
The problem is that I do not know where to put the json file and what the path would be.
Is there a standard folder and path to store this kind of files? Or is there a different way to populate the dao class?
I managed to find a solution which was pretty simple:
JSONParser jsonParser = new JSONParser();
try {
//get JSON file's path
InputStream in = this.getClass().getResourceAsStream("/data/posts.json");
BufferedReader br = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
//Read JSON file
Object obj = jsonParser.parse(br.readLine());
for (Object p : (JSONArray) obj) {
JSONObject post = (JSONObject) p;
//add post to mapping
this.addPost(new Post(generateId(),
(String)post.get("user"),
(String)post.get("title"),
(String)post.get("date")));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}
Note: my json file consisted of only one line (as text file) so that is why BufferedReader.readLine() was enough

Get JSONArray and write to JSONArray

I have the following object:
{
"some_prop": "sweetvalue",
"some_list": ["0f9f822cd7e64000ac056ebc17b82f1d", "0f9f82223094fj7b82f1d"]
}
And I'm trying to get some_list and write to some_list, afterwards saving to a file. using the following code:
public String getData(String key) { // this is confusion should be getConfigValue
String data = getConfig();
JSONObject jsonData;
Object content = null;
try {
jsonData = new JSONObject(data);
if (key != null) {
content = jsonData.getString(key);
} else {
content = jsonData.toString();
}
} catch (JSONException e) {
e.printStackTrace();
}
return content.toString();
}
private void saveFile(String data) {
File file = configFile;
try (FileOutputStream fop = new FileOutputStream(file)) {
if (!file.exists()) file.createNewFile();
byte[] contentInBytes = data.getBytes();
fop.write(contentInBytes);
fop.flush();
fop.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void appendToArrayValue(String uuid) {
JSONObject configData = new JSONObject(getConfig());
JSONArray mutedPlayers = configData.getJSONArray("some_list");
JSONArray uuidArray = new JSONArray(uuid);
JSONArray newArray = concatArray(mutedPlayers, uuidArray);
JSONObject newConfigData = configData.put("some_list", newArray);
saveFile(newConfigData.toString());
}
When trying to run this code, I get the following error:
org.json.JSONException: A JSONArray text must start with '[' at 1 [character 2 line 1]
I'm not sure what's really wrong, I know my code is terrible but that's it.
Looks like the error is at line JSONArray uuidArray = new JSONArray(uuid);?
Because prevoius line JSONArray mutedPlayers = configData.getJSONArray("some_list"); should work fine.
If so, you are passing not an array to new JSONArray(uuid) since uuid is your whole JSON object.

Extract value from Json using Gson

I am trying to extract values from JSON from the URL provided below using GSON java library:
http://api.wunderground.com/api/b28d047ca410515a/forecast/q/-33.912,151.013.json
I have successfully used the code provided below to extract data from URL below:
http://api.wunderground.com/api/b28d047ca410515a/conditions/q/-33.912,151.013.json
Code:
String url = "http://api.wunderground.com/api/b28d047ca410515a/conditions/q/-33.912,151.013.json";
String url2 = "http://api.wunderground.com/api/b28d047ca410515a/forecast/q/-33.912,151.013.json";
InputStream is = null;
try {
is = new URL(url).openStream();
BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
String jsonText = readAll(rd);
JsonElement je = new JsonParser().parse(jsonText);
System.out.println("Current Temperature:" + getAtPath(je, "current_observation/temp_c").getAsString() );
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (is != null)
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
However I am getting exception trying to extract from url2 as per code below , it seems to be a more complicated json to get values from, any help please?
// below code not working
weather_icon_url = getAtPath(je, "current_observation/icon_url").getAsString();
is = new URL(url2).openStream();
BufferedReader rd2 = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
String jsonText2 = readAll(rd2);
JsonElement je2 = new JsonParser().parse(jsonText2);
System.out.println("max Temperature:" + getAtPath(je2, "forecast/simpleforecast/forecastday/high/celsius").getAsString() );
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (is != null)
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
getAtPath code:
private static JsonElement getAtPath(JsonElement e, String path) {
JsonElement current = e;
String ss[] = path.split("/");
for (int i = 0; i < ss.length; i++) {
current = current.getAsJsonObject().get(ss[i]);
}
return current;
}
The problem you are facing is because there is an issue with the getAtPath implementation.
[{"date":{"epoch":"1459152000"... represents a JSONArray which the method is trying to access as JSONObject. Hence the IllegalStateException.
JsonObject com.google.gson.JsonElement.getAsJsonObject()
convenience method to get this element as a JsonObject. If the element
is of some other type, a IllegalStateException will result. Hence it
is best to use this method after ensuring that this element is of the
desired type by calling isJsonObject() first.
You can update and use something like below, as of now it returns only the first element.
private static JsonElement getAtPath(JsonElement e, String path) {
JsonElement current = e;
String ss[] = path.split("/");
for (int i = 0; i < ss.length; i++) {
if(current instanceof JsonObject){
current = current.getAsJsonObject().get(ss[i]);
} else if(current instanceof JsonArray){
JsonElement jsonElement = current.getAsJsonArray().get(0);
current = jsonElement.getAsJsonObject().get(ss[i]);
}
}
return current;
}
This should work:
System.out.println("max Temperature:" + getAtPath(je2, "forecast/simpleforecast/forecastday/high/celsius").getAsString() );

Is there a way to parse JSON with java? [duplicate]

This question already has answers here:
Converting JSON data to Java object
(14 answers)
Closed 6 years ago.
Here is what I have so far:
public Bitmap getAlbumCover(Context context, String song, String artist) {
this.context = context;
song = song.replace(" ", "%20");
artist = artist.replace(" ", "%20");
try {
conn = new URL("https://api.spotify.com/v1/search?q=track" + song + ":%20artist:" + artist + "&type=track)").openConnection();
} catch (IOException e) {
e.printStackTrace();
}
if (conn != null)
conn.setDoOutput(true);
try {
reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
if (reader != null) {
// Read Server Response
String line2 = null;
try {
while ((line2 = reader.readLine()) != null) {
sb.append(line2);
}
} catch (IOException e) {
e.printStackTrace();
}
try {
json = new JSONArray(sb.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
JSONParser parser= new JSONParser();
try {
JSONObject jsonObject = (JSONObject) parser.parse(reader);
try {
array = (JSONArray) jsonObject.get("items");
} catch (JSONException e) {
e.printStackTrace();
}
// take each value from the json array separately
} catch (IOException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
The JSON I am using is located here:
https://api.spotify.com/v1/search?q=track:Ready%20To%20Fall%20artist:rise%20against%20&type=track
I am trying to get the image url located in the images array and the preview_track url located in items.
I use Jackson library to parse JSON to java opbject.
if you create your java object with the same structure as JSON this can be done using this:
ObjectMapper mapper = new ObjectMapper();
mapper.readValue(jsonUrl, YourClass.class);
So your OBJECT will have tracks and then tracks will have object album and album will have object other details. Just structure it as the JSON is and you are there.

How to convert inputsource to inputstream which will feed to stringreader as the parameter?

I have requirement, where i need to get the xml from the server to parse if it is present and if not take the file from assets folder.
What ever the xml i'm getting using inputstream im passing it as the parameter for StringReader for further processing. I'm using XmlPullParser for parsing.
But i'm not able to pass the inputsource paramter to stringreader for further parsing. I don't to use document reader. Please find the code as below.
private void readSynconfiguration( )
{
XmlParser xmlparser = new XmlParser();
try {
String strFromMbo = getDataFromMBO();
if(strFromMbo != null && !strFromMbo.isEmpty()) { // first
InputSource is = new InputSource(new StringReader(strFromMbo));
// result = getStringFromInputStream(is);
}
else {
context = RetailExecutionApplication.getApp().getApplicationContext();
InputStream stream = context.getAssets().open("syncSettings.xml");
result = getStringFromInputStream(stream);
}
} catch (IOException e) {
syncSetting = false;
e.printStackTrace();
}
StringReader labelReader = new StringReader(result);
try {
if(syncSetting) {
labelSharedInstance.clear();
labelSyncDetails = xmlparser.LabelsParse(labelReader);
labelSharedInstance = labelSyncDetails;
}
} catch (XmlPullParserException e) {
syncSetting = false;
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Please help me in this regard.
You can not pass inputsorce object directly to StringReader. First of all you convert inputsorce to reader as follows :
Reader reader = yourInputSource.getCharacterStream();
String result = reader.toString();
StringReader labelReader = new StringReader(result);
I think you are confusing things. The XmlPullParser.setInput() method takes Reader, so that's what you need to provide.
In case 1 (from database), you have a String in strFromMbo, so just wrap with a StringReader.
In case 2 (from file), you have two choices:
Load entire file into memory as a String. This is what you're doing.
Use a FileReader. Uses less memory.
In both cases, remember to close your resources.
I don't understand what "inputsource" has to do with anything.
String xml = getDataFromMBO();
if (xml == null || xml.isEmpty()) {
context = RetailExecutionApplication.getApp().getApplicationContext();
try (InputStream stream = context.getAssets().open("syncSettings.xml")) {
xml = getStringFromInputStream(stream);
} catch (IOException e) {
syncSetting = false;
e.printStackTrace();
}
}
if (syncSetting) {
try {
labelSharedInstance.clear();
labelSyncDetails = new XmlParser().LabelsParse(new StringReader(xml));
labelSharedInstance = labelSyncDetails;
} catch (XmlPullParserException e) {
syncSetting = false;
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

Categories

Resources