I have a JSON file (myjsonfile.json) which stores the folder structure along with file contents as a JSON. It is as follows:
{
"name":"folder1",
"type":"directory",
"children":[
{"name":"info",
"type":"directory",
"children": [
{
"name":"info1.txt",
"type":"file",
"content": ["abcd", "efgh", "ijk"]
}]
},
{"name":"data",
"type":"directory",
"children": [{
"name":"data1.txt",
"type":"file",
"content": ["abcd", "xyz"]
}]
}
]
}
What I want to do is access the content of either of the two text files (info1.txt or data1.txt) dynamically and store them as a List of Strings. By dynamically I mean that the filename i.e., the key (info1.txt or data1.txt) will be provided by the user.
I was able to parse and get the value in a static way by using org.json library like this:
File file = new File(myfilepath/myjsonfile.json);
String jsonContent = null;
try {
content = FileUtils.readFileToString(file, "utf-8");
} catch (IOException e) {
e.printStackTrace();
}
// Convert JSON string to JSONObject
JSONObject jsonObj = new JSONObject(jsonContent);
JSONArray children = jsonObj.getJSONArray("children");
System.out.println(children.toString());
JSONObject child0 = children.getJSONObject(0);
System.out.println(child0.toString());
// and so on...
However, I can't figure out how to make this dynamic and store the file contents as a List of Strings based on the user input of the filename.
Can someone please help me out?
EDIT: Clarified the question. myfilepath here refers to the file path of the JSON file (myjsonfile.json).
You need to loop through each object and see if name has the file you are looking for. I would recommend you use a more verbose JSON processing library such as Jackson or Gson to make things easier. However, given your current implementation, you want to do something along the lines of:
if(jsonObj.has("children")) {
JSONArray mainChild = jsonObj.getJSONArray("children");
for(int i=0; i < mainChild.length(); i++) {
if(((JSONObject)mainChild.get(i)).has("children")) {
JSONArray child = ((JSONObject)mainChild.get(i)).getJSONArray("children");
for(int j=0; j < child.length(); j++) {
JSONObject obj = child.getJSONObject(j);
if(obj.has("name")
&& fileNameToLookFor.equals(obj.getString("name"))) {
if(obj.has("content")) {
return obj.getJSONArray("content");
}
return null;
}
}
}
}
return null;
}
Implement your own tree-node-walker:
class NodeWalker {
private final JSONObject object;
public NodeWalker(JSONObject object) {
this.object = object;
}
public List<String> findContentFor(String name) {
LinkedList<JSONObject> queue = new LinkedList<>();
queue.add(object);
while (queue.size() > 0) {
JSONObject next = queue.pop();
Object fileName = next.get("name");
final String contentName = "content";
if (fileName != null && fileName.equals(name) && next.has(contentName)) {
JSONArray content = next.getJSONArray(contentName);
if (content == null) {
return Collections.emptyList();
}
List<String> result = new ArrayList<>();
IntStream.range(0, content.length()).forEach(i -> result.add(content.getString(i)));
return result;
}
final String childrenName = "children";
if (next.has(childrenName)) {
JSONArray array = next.getJSONArray(childrenName);
IntStream.range(0, array.length()).forEach(i -> queue.add(array.getJSONObject(i)));
}
}
return Collections.emptyList();
}
}
Simple usage:
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.File;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.IntStream;
public class ProfileApp {
public static void main(String[] args) throws Exception {
File jsonFile = new File("./resource/test.json").getAbsoluteFile();
List<String> strings = Files.readAllLines(jsonFile.toPath());
String json = String.join("", strings);
JSONObject jsonObj = new JSONObject(json);
NodeWalker nodeWalker = new NodeWalker(jsonObj);
String[] files = {"info1.txt", "data1.txt", "data2.txt"};
for (String file : files) {
System.out.println(file + " contents -> " + nodeWalker.findContentFor(file));
}
}
}
prints:
info1.txt contents -> [abcd, efgh, ijk]
data1.txt contents -> [abcd, xyz]
data2.txt contents -> []
Gson
Much easier to use Gson library and class model of your JSON payload. Let's create a class:
class FileNode {
private String name;
private String type;
private List<FileNode> children;
private List<String> content;
public List<String> findContent(String name) {
LinkedList<FileNode> queue = new LinkedList<>();
queue.add(this);
while (queue.size() > 0) {
FileNode next = queue.pop();
if (next.name.equals(name)) {
return next.content;
}
if (next.children != null) {
queue.addAll(next.children);
}
}
return Collections.emptyList();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public List<FileNode> getChildren() {
return children;
}
public void setChildren(List<FileNode> children) {
this.children = children;
}
public List<String> getContent() {
return content;
}
public void setContent(List<String> content) {
this.content = content;
}
#Override
public String toString() {
return "FileNode{" +
"name='" + name + '\'' +
", type='" + type + '\'' +
", children=" + children +
", content=" + content +
'}';
}
}
Which we can use as below:
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.io.File;
import java.io.FileReader;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
public class GsonApp {
public static void main(String[] args) throws Exception {
File jsonFile = new File("./resource/test.json").getAbsoluteFile();
Gson gson = new GsonBuilder()
.setPrettyPrinting()
.create();
FileNode root = gson.fromJson(new FileReader(jsonFile), FileNode.class);
String[] files = {"info1.txt", "data1.txt", "data2.txt"};
for (String file : files) {
System.out.println(file + " contents -> " + root.findContent(file));
}
}
}
Above code prints:
info1.txt contents -> [abcd, efgh, ijk]
data1.txt contents -> [abcd, xyz]
data2.txt contents -> []
I have a List<String> data which is like:
{"0":["passFrom","3/9/2018","3/9/2018","anotherMethod","but"],"1":["googleForAlongTIme","3/9/2018","3/9/2018","stillCannotConvert","theLinkHashMap"]}
I need to store to a linkeHashMap with the above data, so far I had try something like below.
ArrayList<String> listdata = new ArrayList<String>();
Map<Integer, List<String>> listMap = new LinkedHashMap<Integer, List<String>>();
if (jsonArray.getString(0).trim()!= null && !jsonArray.getString(0).isEmpty()) {
for (int i = 0; i < jsonArray.length(); i++){
listdata.add(jsonArray.getString(i)); // here is the data which shown above
//trying to use split at here but find out `**["passFrom","3/9/2018","3/9/2018","anotherMethod","but"],"1"**` is not the correct data
/*List<String> bothList= Arrays.asList(listdata.get(i).toString().split(":"));
for (String string : bothList) {
List<String> tempData=Arrays.asList(bothList.toString());
listMap.put(i, tempData);
System.out.println("TeST: " + string);
}*/
}
}
Need some hints and help here, as my final aim is to get the 0,1 integer and below data to store inside the listMap
"passFrom","3/9/2018","3/9/2018","anotherMethod","but"
"googleForAlongTIme","3/9/2018","3/9/2018","stillCannotConvert","theLinkHashMap"
Try this:
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.util.List;
import java.util.Map;
public class ParseJson {
public static void main(String[] args) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
final String jsonStr = "{\"0\":[\"passFrom\",\"3/9/2018\",\"3/9/2018\",\"anotherMethod\",\"but\"],\"1\":[\"googleForAlongTIme\",\"3/9/2018\",\"3/9/2018\",\"stillCannotConvert\",\"theLinkHashMap\"]}";
Map<Integer, List<String>> map = objectMapper.readValue(jsonStr, new TypeReference<LinkedHashMap<Integer, List<String>>>(){});
for (Map.Entry<Integer, List<String>> entry : map.entrySet()) {
System.out.printf("For item \"%d\", values are:\n", entry.getKey());
for (String value : entry.getValue()) {
System.out.printf("\t[%s]\n", value);
}
}
}
}
Outputs:
For item "0", values are:
[passFrom]
[3/9/2018]
[3/9/2018]
[anotherMethod]
[but]
For item "1", values are:
[googleForAlongTIme]
[3/9/2018]
[3/9/2018]
[stillCannotConvert]
[theLinkHashMap]
I extract some data from a http site and now I want to format this using JSON . I watched some examples but i don't understand how to do that exactly .I want something like that :
{
Product name:"Samsung..."
{ review 1:"..."
review 2:"..."
}
}
Also my code don't iterate over all reviews, it stops at page 1 ,and there is 10 more pages and i want to get like 20-30 reviews at least. There is what i did until now :
import java.io.IOException;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
public class JsoupMain {
private static int nr = 1;
public static void main(String[] args) {
Document document = null;
try {
document = Jsoup.connect("http://www.emag.ro/telefon-mobil-samsung- galaxy-j5-2016-dual-sim-16gb-4g-gold-sm-j510fzdurom/pd/DQD3B7BBM/").get();
String title = document.title();
System.out.println("Title: " + title);
Elements review = document.select("div.product-review-body");
for (Element rev : review) {
System.out.println("Review : " + nr + " :" + rev.text() + "\n");
nr++;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
See this answer for a similar question - Parsing table html with Jsoup In your case it might look like this:
JSONObject root = new JSONObject();
JSONArray reviews = new JSONArray();
root.put("name", "Product Name");
for (int i=0; i < elements.size(); i++){
JSONObject review = new JSONObject();
review.put("review"+i , elements.get(i).text());
reviews.add(review);
}
root.put("reviews", reviews);
The JSON output for root would look like this:
{
"name":"Product Name",
"reviews":[
{
"review0":"ok"
},
{
"review1":"awesome"
}
]
}
I want to make this code to show info exactly like that:
{ Reviews:
{ review 1: "..."}
{ review 2: "..."}
................
................
}
In present my code is printing info's like that: "Reviews":[[{"Review 0":"Foarte multumit Un telefon foarte bun. Ce m-a impresionat este camera foto care face niste poze foarte bune"},{"R............}
import java.io.IOException;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
public class JsoupMain {
private static int nr = 1;
public static void main(String[] args) {
Document document = null;
try {
document = Jsoup.connect("http://www.emag.ro/telefon-mobil-samsung-galaxy-j5-2016-dual-sim-16gb-4g-gold-sm-j510fzdurom/pd/DQD3B7BBM/").get();
String title = document.title();
System.out.println("Product name : " + title);
Elements review = document.select("div.product-review-body");
JSONObject mainObject = new JSONObject();
JSONObject root = new JSONObject();
JSONArray list = new JSONArray();
root.put("Product name", title);
for (int i = 0; i < review.size(); i++) {
JSONObject revieww = new JSONObject();
revieww.put("Review " + i, review.get(i).text());
list.put(revieww);
}
mainObject.accumulate("Reviews", list);
System.out.println(mainObject);
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Replace your code from Elements review = document.select("div.product-review-body");... to ... System.out.println(mainObject); with the following code snippet.
Elements review = document.select("div[class=product-review-body]");
JSONObject parent = new JSONObject();
parent.put("Product name", title);
JSONArray reviews = new JSONArray();
int i = 1;
for (Element rev : review) {
reviews.put(new JSONObject().put("review" + i, rev.text()));
i++;
}
parent.put("Reviews", reviews);
System.out.println(parent);
Hope this helps.
I am trying to parse the content of JSON file text.json by using Jackson library.
What I want is to make a java method in the following code to get all keys and values of it, but so far in my code I get only the first key and the first value of the JSON file.
Here is my Java class:
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import org.codehaus.jackson.JsonFactory;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
public class JacksonStreamExample {
public static void main(String[] args) {
try {
//Create a JsonFactory instance
JsonFactory factory = new JsonFactory();
//Create a JsonParser instance to read from file c:\\text.json
JsonParser jParser = factory.createJsonParser(new File("c:\\text.json"));
/*Create an ObjectMapper instance to provide a pointer
* to root node of the tree after reading the JSON
*/
ObjectMapper mapper = new ObjectMapper(factory);
//Create tree from JSON
JsonNode rootNode = mapper.readTree(jParser);
Iterator<Map.Entry<String,JsonNode>> fieldsIterator = rootNode.getFields();
while (fieldsIterator.hasNext()) {
Map.Entry<String,JsonNode> field = fieldsIterator.next();
System.out.println("Key: " + field.getKey() + "\tValue:" + field.getValue());
}
jParser.close();
} catch (JsonGenerationException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
My Eclipse output is the following which creates only 1 pair(key-value):
Key: cells Value:[{"type":"basic.Circle","size":{"width":90,"height":54},"position":{"x":-80,"y":200},"angle":0,"id":"cae4c219-c2cd-4a4b-b50c-0f269963ca24","embeds":"","z":1,"wi_name":"START","wi_displayName":"START","wi_description":"","wi_join":"<None>","wi_split":"<None>","wi_performingRole":"<None>","wi_expected_activity_time":null,"wi_expected_user_time":null,"wi_maximum_activity_time":null,"wi_initial_delay":null,"wi_time_unit":"Seconds","wi_required_transitions_for_AND_JOIN":null,"wi_custom_page":"","attrs":{"circle":{"fill":"#000000","width":50,"height":30,"stroke-width":1,"stroke-dasharray":"0"},"text":{"font-size":10,"text":"START","fill":"#ffffff","font-family":"Arial","stroke":"#000000","stroke-width":0,"font-weight":400}}},{"type":"basic.Circle","size":{"width":90,"height":54},"position":{"x":210,"y":200},"angle":0,"id":"d23133e0-e516-4f72-8127-292545d3d479","embeds":"","z":2,"wi_name":"END","wi_displayName":"END","wi_description":"","wi_join":"<None>","wi_split":"<None>","wi_performingRole":"<None>","wi_expected_activity_time":null,"wi_expected_user_time":null,"wi_maximum_activity_time":null,"wi_initial_delay":null,"wi_time_unit":"Seconds","wi_required_transitions_for_AND_JOIN":null,"wi_custom_page":"","attrs":{"circle":{"fill":"#000000","width":50,"height":30,"stroke-width":1,"stroke-dasharray":"0"},"text":{"font-size":10,"text":"END","fill":"#ffffff","font-family":"Arial","stroke":"#000000","stroke-width":0,"font-weight":400}}},{"type":"basic.Rect","position":{"x":-80,"y":370},"size":{"width":90,"height":54},"angle":0,"id":"a53898a5-c018-45c4-bd3f-4ea4d69f58ed","embeds":"","z":3,"wi_name":"ACTIVITY_1","wi_displayName":"ACTIVITY 1","wi_description":"","wi_join":"<None>","wi_split":"<None>","wi_performingRole":"<None>","wi_expected_activity_time":null,"wi_expected_user_time":null,"wi_maximum_activity_time":null,"wi_initial_delay":null,"wi_time_unit":"Seconds","wi_required_transitions_for_AND_JOIN":null,"wi_custom_page":"","attrs":{"rect":{"width":50,"height":30,"rx":2,"ry":2,"stroke-width":1,"stroke-dasharray":"0"},"text":{"text":"Activity","font-size":10,"font-family":"Arial","stroke":"#000000","stroke-width":0,"font-weight":400}}},{"type":"basic.Rect","position":{"x":220,"y":370},"size":{"width":90,"height":54},"angle":0,"id":"e2bd21f2-508d-44b9-9f68-e374d4fa87ea","embeds":"","z":4,"wi_name":"ACTIVITY_2","wi_displayName":"ACTIVITY 2","wi_description":"","wi_join":"<None>","wi_split":"<None>","wi_performingRole":"<None>","wi_expected_activity_time":null,"wi_expected_user_time":null,"wi_maximum_activity_time":null,"wi_initial_delay":null,"wi_time_unit":"Seconds","wi_required_transitions_for_AND_JOIN":null,"wi_custom_page":"","attrs":{"rect":{"width":50,"height":30,"rx":2,"ry":2,"stroke-width":1,"stroke-dasharray":"0"},"text":{"text":"Workitem","font-size":10,"font-family":"Arial","stroke":"#000000","stroke-width":0,"font-weight":400}}},{"type":"link","source":{"id":"cae4c219-c2cd-4a4b-b50c-0f269963ca24"},"target":{"id":"d23133e0-e516-4f72-8127-292545d3d479"},"router":{"name":"manhattan"},"labels":[{"position":0.5,"attrs":{"text":{"text":"Name"}}}],"id":"60ee7ff7-3a3b-487d-b581-49027e7bebe4","embeds":"","z":5,"attrs":{".marker-source":{"d":"M 10 0 L 0 5 L 10 10 z","transform":"scale(0.001)"},".marker-target":{"d":"M 10 0 L 0 5 L 10 10 z"},".connection":{"stroke":"black"}}},{"type":"link","source":{"id":"a53898a5-c018-45c4-bd3f-4ea4d69f58ed"},"target":{"id":"e2bd21f2-508d-44b9-9f68-e374d4fa87ea"},"router":{"name":"manhattan"},"labels":[{"position":0.5,"attrs":{"text":{"text":"Name"}}}],"id":"cea0d1c2-2c18-4bd7-ba35-d94918c6fc9b","embeds":"","z":6,"attrs":{".marker-source":{"d":"M 10 0 L 0 5 L 10 10 z","transform":"scale(0.001)"},".marker-target":{"d":"M 10 0 L 0 5 L 10 10 z"},".connection":{"stroke":"black"}}}]
How will I do it please?
In the above code sample, the nested/Hierarchical Structure is not considered of json value and it directly prints it as field.getValue().
You'll have to check for the type of value using
if(field.getValue().isObject())
{
parse(field.getValue())
}
The Parse Method could be as follows
private void parse(JsonNode jsonNode)
{
Iterator<Map.Entry<String, JsonNode>> fieldsIterator = jsonNode.getFields();
while (fieldsIterator.hasNext())
{
Map.Entry<String, JsonNode> field = fieldsIterator.next();
if (field.getValue().isObject())
{
parse(field.getValue());
}
System.out.println("Key: " + field.getKey() + "\tValue:" + field.getValue());
}
}
Then you have to just call the parse method for the rootNode.
I solved my problem by changing JSON library.
I used json-simple-1.1.1
My final code that worked is the following:
package jsontoxml;
import java.io.*;
import org.json.simple.parser.JSONParser;
import org.json.simple.*;
import java.util.*;
public class JacksonStreamExample {
public static void main(String[] args) {
JSONParser parser = new JSONParser();
try {
Object obj = parser.parse(new FileReader("text.json"));
JSONObject jsonObject = (JSONObject) obj;
JSONArray cells = (JSONArray) jsonObject.get("cells");
Iterator<JSONObject> iterator = cells.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
When jsonobject is converted to String or long it returns null. Why?
My JSON file:
{
"memberships": [
{
"project": {
"id": 30483134480107,
"name": "Asana Integrations"
},
"section": null
}
]
}
And my code:
package jsontest;
import java.beans.Statement;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
public class MoreComplexJson {
private static final String filePath = "C:\\jsonTestFile.json";
public static void main(String[] args) {
try {
FileReader reader = new FileReader(filePath);
JSONParser jsonParser = new JSONParser();
JSONObject jsonObject = (JSONObject) jsonParser.parse(reader);
JSONArray memberships = (JSONArray) jsonObject.get("memberships");
for (int z = 0; z < memberships.size(); z++) {
Iterator m = memberships.iterator();
// take each value from the json array separately
while (m.hasNext()) {
JSONObject innerObj = (JSONObject) m.next();
Long id = (Long) innerObj.get("id");
String name = (String) innerObj.get("name");
System.out.println("id " + id + " with name " + name);
}
}
}
catch (FileNotFoundException ex) {
ex.printStackTrace();
System.out.println(ex + "");
}
catch (IOException ex) {
ex.printStackTrace();
ex.printStackTrace();
System.out.println(ex + "");
}
catch (ParseException ex) {
ex.printStackTrace();
ex.printStackTrace();
System.out.println(ex + "");
}
catch (NullPointerException ex) {
ex.printStackTrace();
ex.printStackTrace();
System.out.println(ex + "");
}
}
}
The output:
id null with name null
id and name belongs to the project JSONObject so get those two values using the project JSONObject
Try this for loop
for (int z = 0; z < memberships.size(); z++) {
JSONObject m = (JSONObject) memberships.get(z);
JSONObject innerObj = (JSONObject) m.get("project");
// If you want section
String section = (String) m.get("section");
System.out.println("section " + section);
Long id = (Long) innerObj.get("id");
String name = (String) innerObj.get("name");
System.out.println("id " + id + " with name " + name);
}
The problem is that when you are trying to get id and name you're not taking it from project but from object that contains project. There should be:
JSONObject innerObj = (JsonObject) ((JSONObject) m.next()).get("project)";
This kind of code can get pretty ugly pretty fast. Instead you could use a higher order parser, such as Jackson. Then your code can be much cleaner and you don't have to worry about digging into the conversion of each piece of JSON.