The whole file is an array and there are objects and other arrays (e.g. cars) in the whole array of the file.
As you say, the outermost layer of your JSON blob is an array. Therefore, your parser will return a JSONArray. You can then get JSONObjects from the array ...
JSONArray a = (JSONArray) parser.parse(new FileReader("c:\\exer4-courses.json"));
for (Object o : a)
{
JSONObject person = (JSONObject) o;
String name = (String) person.get("name");
System.out.println(name);
String city = (String) person.get("city");
System.out.println(city);
String job = (String) person.get("job");
System.out.println(job);
JSONArray cars = (JSONArray) person.get("cars");
for (Object c : cars)
{
System.out.println(c+"");
}
}
For reference, see "Example 1" on the json-simple decoding example page.
Answer from Greg Kopff on Stack OverflowThe whole file is an array and there are objects and other arrays (e.g. cars) in the whole array of the file.
As you say, the outermost layer of your JSON blob is an array. Therefore, your parser will return a JSONArray. You can then get JSONObjects from the array ...
JSONArray a = (JSONArray) parser.parse(new FileReader("c:\\exer4-courses.json"));
for (Object o : a)
{
JSONObject person = (JSONObject) o;
String name = (String) person.get("name");
System.out.println(name);
String city = (String) person.get("city");
System.out.println(city);
String job = (String) person.get("job");
System.out.println(job);
JSONArray cars = (JSONArray) person.get("cars");
for (Object c : cars)
{
System.out.println(c+"");
}
}
For reference, see "Example 1" on the json-simple decoding example page.
You can use jackson library and simply use these 3 lines to convert your json file to Java Object.
ObjectMapper mapper = new ObjectMapper();
InputStream is = Test.class.getResourceAsStream("/test.json");
testObj = mapper.readValue(is, Test.class);
You can use the below methods to read from a file and convert the JSON array to a List of Questions.
public String readJsonFromFile(String filePath) throws IOException, ParseException {
String json = Files.readString(Paths.get("file path"));
return new JSONParser().parse(json).toString();
}
public List<Question> convert(String JsonString) throws JsonMappingException, JsonProcessingException {
ObjectMapper om = new ObjectMapper();
CollectionType typeReference =
TypeFactory.defaultInstance().constructCollectionType(List.class, Question.class);
List<Question> questions = om.readValue(JsonString, typeReference);
return questions;
}
If your JSON keys and Java class fields are different, use @JsonPropery annotation to map keys to fields
import com.fasterxml.jackson.annotation.JsonProperty;
public class Question {
@JsonProperty("question")
private String title;
@JsonProperty("answer 1")
private String a1;
@JsonProperty("answer 2")
private String a2;
@JsonProperty("answer 3")
private String a3;
@JsonProperty("correct answer")
private String cA;
//setters & getters
}
Required Jars:
jackson-annotations.jar
jackson-core.jar
jackson-databind.jar
json-simple.jar //used to parse Json file to String
You have two steps
Get JSON string from the file, use read file from assets
Extract items from the JSON string use How do I convert a JSON array into a Java List. I'm using svenson
Reading a JSON File from resources and creating a List of Objects in Java - Stack Overflow
How to convert JSON string into List of Java object? - Stack Overflow
How to read JSON file of objects into a list in Java with Jackson - Stack Overflow
How to read JSON to a list of generic objects in java? - Stack Overflow
Videos
There are lots of API's and libraries are present but I prefer to use org.json API suggested by json.org
you can also go for GSON library which is one of the best library for serialize and deserialize Java objects to (and from) JSON.
here's the quick demo of reading above JSON with org.json API.
import org.json.JSONObject;
import org.json.JSONArray;
public class HelloWorld {
public static void main(String[] args) {
String jsonString = "[ { \"name\": \"Andrew\", \"age\": 21, \"parents\": [ { \"name\": \"Joseph\", \"age\": 18 }, { \"name\": \"Joseph\", \"age\": 18 } ] }, { \"name\": \"Maria\", \"age\": 35, \"parents\": [ { \"name\": \"Kassandra\", \"age\": 16 }, { \"name\": \"Abigail\", \"age\": 22 } ] } ]";
JSONArray json = new JSONArray(jsonString);
for(int i=0; i<json.length(); i++){
JSONObject j = json.getJSONObject(i);
System.out.println(j + "\n------");
}
}
}
Use jackson library. Here is a snippet.
public static void main(final String[] args) throws JsonProcessingException {
final List<Child> children = new ObjectMapper().readValue(
readFromFile("data.json"), new TypeReference<List<Child>>() {
});
System.out.println(children);
}
public static String readFromFile(final String resourcePath) {
final ClassPathResource resource = new ClassPathResource(resourcePath);
try {
final InputStream inputStream = resource.getInputStream();
return readFromInputStream(inputStream);
} catch (final IOException var4) {
return "";
}
}
private static String readFromInputStream(final InputStream inputStream) throws IOException {
final StringBuilder resultStringBuilder = new StringBuilder();
final BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
Throwable var3 = null;
try {
String line;
try {
while ((line = br.readLine()) != null) {
resultStringBuilder.append(line).append("\n");
}
} catch (final Throwable var12) {
var3 = var12;
throw var12;
}
} finally {
if (br != null) {
if (var3 != null) {
try {
br.close();
} catch (final Throwable var11) {
var3.addSuppressed(var11);
}
} else {
br.close();
}
}
}
return resultStringBuilder.toString();
}
You are asking Jackson to parse a StudentList. Tell it to parse a List (of students) instead. Since List is generic you will typically use a TypeReference
List<Student> participantJsonList = mapper.readValue(jsonString, new TypeReference<List<Student>>(){});
For any one who looks for answer yet:
1.Add jackson-databind library to your build tools like Gradle or Maven
2.in your Code:
ObjectMapper mapper = new ObjectMapper();
List<Student> studentList = new ArrayList<>();
studentList = Arrays.asList(mapper.readValue(jsonStringArray, Student[].class));
Definitely the easiest way to do that is using Gson's default parsing function fromJson().
There is an implementation of this function suitable for when you need to deserialize into any ParameterizedType (e.g., any List), which is fromJson(JsonElement json, Type typeOfT).
In your case, you just need to get the Type of a List<String> and then parse the JSON array into that Type, like this:
import java.lang.reflect.Type;
import com.google.gson.reflect.TypeToken;
JsonElement yourJson = mapping.get("servers");
Type listType = new TypeToken<List<String>>() {}.getType();
List<String> yourList = new Gson().fromJson(yourJson, listType);
In your case yourJson is a JsonElement, but it could also be a String, any Reader or a JsonReader.
You may want to take a look at Gson API documentation.
Below code is using com.google.gson.JsonArray.
I have printed the number of element in list as well as the elements in List
import java.util.ArrayList;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
public class Test {
static String str = "{ "+
"\"client\":\"127.0.0.1\"," +
"\"servers\":[" +
" \"8.8.8.8\"," +
" \"8.8.4.4\"," +
" \"156.154.70.1\"," +
" \"156.154.71.1\" " +
" ]" +
"}";
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
JsonParser jsonParser = new JsonParser();
JsonObject jo = (JsonObject)jsonParser.parse(str);
JsonArray jsonArr = jo.getAsJsonArray("servers");
//jsonArr.
Gson googleJson = new Gson();
ArrayList jsonObjList = googleJson.fromJson(jsonArr, ArrayList.class);
System.out.println("List size is : "+jsonObjList.size());
System.out.println("List Elements are : "+jsonObjList.toString());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
OUTPUT
List size is : 4
List Elements are : [8.8.8.8, 8.8.4.4, 156.154.70.1, 156.154.71.1]
You should definitly have a look at the Jackson Streaming API (https://www.baeldung.com/jackson-streaming-api). I used it myself for GB large JSON files. The great thing is you can divide your JSON into several smaller JSON objects and then parse them with mapper.readTree(parser). That way you can combine the convenience of normal Jackson with the speed and scalability of the Streaming API.
Related to your problem:
I understood that your have a really large array (which is the reason for the file size) and some much more readable objects:
e.g.:
[ // 40GB
{}, // Only 400 MB
{},
]
What you can do now is to parse the file with Jackson's Streaming API and go through the array. But each individual object can be parsed as "regular" Jackson object and then processed easily.
You may have a look at this Use Jackson To Stream Parse an Array of Json Objects which actually matches your problem pretty well.
is there a way to read this file using BufferedReader and then to push object by object ?
Of course, not. Even you can open this file how you can store 40GB as java objects in memory? I think you don't have such amount of memory in you computers (but technically using ObjectMapper you should have about 2 times more operation memory - 40GB for store json + 40GB for store results as java objects = 80 GB).
I think you should use any way from this questions, but store information in databases or files instead of memory. For example, if you have millions rows in json, you should parse and save every rows to database without keeping it all in memory. And then you can get this data from database step by step (for example, not more then 1GB for every time).