简体   繁体   中英

Parsing JSON data into model objects in Java

I haven't worked with JSON data before, thus the question. I've the following JSON object in a file.

{
    "courses": [
        { "id":998", "name":"Java Data Structures", "teacherId":"375" },
        { "id":"999", "name":"Java Generics", "teacherId":"376" }

    ],
    "teachers": [
        { "id":"375", "firstName":"Amiyo", "lastName":"Bagchi"},
        { "id":"376", "firstName":"Dennis", "lastName":"Ritchie"}    
    ]
}

Here are my model Objects.

public class Course {

    private int _id;
    private String _name;
    private Teacher _teacher;
}

public class Teacher {
    private int _id;
    private String _firstName;
    private String _lastName;
}

My task is to read the JSON Objects and return a list of Model objects.

I've imported the simple.JSON family of jar and here's my code that reads the file.

    FileReader reader = new FileReader(path);
    JSONParser parser = new JSONParser();
    Object obj = parser.parse(reader);

    JSONObject jsonObject = (JSONObject) obj;

My question is,

  1. How do I parse the JSON document into my Model objects?
  2. If the input file is JSON but of a different format how do I throw exception/handle the anomaly?

Any help appreciated.

UPDATE I suggest you use JSON parser to parse the data:

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
import java.util.HashMap;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;

class Course {

    public int _id;
    public String _name;
    public Teacher _teacher;

    private Course(int id, String name, Teacher teacher){
        this._id = id;
        this._name = name;
        this._teacher = teacher;
    }
    public Course() {

    }
}

class Teacher {
    public int _id;
    public String _firstName;
    public String _lastName;
    private Teacher(int id, String fname, String lname){
        this._id = id;
        this._firstName = fname;
        this._lastName = lname;
    }
    public Teacher(){

    }

}

public class jsontest {

    public static void main(String[] args) throws JSONException, IOException {

//        String JSON_DATA = "{\n"+
//        " \"courses\": [\n"+
//        " { \"id\":\"998\", \"name\":\"Java Data Structures\", \"teacherId\":\"375\" },\n"+
//        " { \"id\":\"999\", \"name\":\"Java Generics\", \"teacherId\":\"376\" }\n"+
//        "\n"+
//        " ],\n"+
//        " \"teachers\": [\n"+
//        " { \"id\":\"375\", \"firstName\":\"Amiyo\", \"lastName\":\"Bagchi\"},\n"+
//        " { \"id\":\"376\", \"firstName\":\"Dennis\", \"lastName\":\"Ritchie\"} \n"+
//        " ]\n"+
//        "}\n"+
//        "";
        // read json file into string
        String JSON_DATA = new String(Files.readAllBytes(Paths.get("path_to_json_file")), StandardCharsets.UTF_8);

        // using a JSON parser
        JSONObject obj = new JSONObject(JSON_DATA);
        // parse "teachers" first
        List<Teacher> listCourses = new ArrayList<Teacher>();
        List<JSONObject> listObjs = parseJsonData(obj,"teachers");
        for (JSONObject c: listObjs) {
            Teacher teacher = new Teacher();
            teacher._id = c.getInt("id");
            teacher._firstName = c.getString("firstName");
            teacher._lastName = c.getString("lastName");
            listCourses.add(teacher);
        }
        // parse "courses" next
        List<Course> resultCourses = new ArrayList<Course>();
        List<JSONObject> listObjs2 = parseJsonData(obj, "courses");

        for (JSONObject c: listObjs2) {
            Course course = new Course();
            course._id = c.getInt("id");
            course._name = c.getString("name");
            int teacherId =  c.getInt("teacherId");
            HashMap<String, Teacher> map = new HashMap<String, Teacher>();
            for (Teacher t: listCourses){
                map.put(Integer.toString(t._id), t);
            }
            course._teacher = map.get(Integer.toString(teacherId));
            resultCourses.add(course);
        }
    }


    public static List<JSONObject> parseJsonData(JSONObject obj, String pattern)throws JSONException {

        List<JSONObject> listObjs = new ArrayList<JSONObject>();
        JSONArray geodata = obj.getJSONArray (pattern);
        for (int i = 0; i < geodata.length(); ++i) {
          final JSONObject site = geodata.getJSONObject(i);
          listObjs.add(site);
        }
        return listObjs;
    }

}

Output:

在此输入图像描述

BTW: The json data in the example has one value whose double quotes are not in pairs. To proceed, it must be fixed.

You should try using Jackson as the JSON parsing library instead. There is a lot more support and features that come with it.

In your case, a couple of annotations to map the JSON properties to the Java fields should be sufficient.

UPDATE : Some code, to show just much better this can be done with Jackson.

public class Course {
    @JsonProperty("id")
    private int _id;
    @JsonProperty("name")
    private String _name;
    @JsonProperty("teacher")
    private Teacher _teacher;
    // ...public getters and setters
}

public class Teacher {
    @JsonProperty("id")
    private int _id;
    @JsonProperty("firstName")
    private String _firstName;
    @JsonProperty("lastName")
    private String _lastName;
    // ...public getters and setters
}

// Container class to conform to JSON structure
public class CoursesDto {
    private List<Teacher> teachers;
    private List<Course> courses;
}

// In your parser place
ObjectMapper mapper = new ObjectMapper();
FileReader reader = new FileReader(path);
CoursesDto dto = mapper.readValue(reader, CoursesDto.class);

The @JsonProperty annotations tell Jackson what JSON key should be used to deserialize. They are not necessary if the property names match the JSON keys. That means that if you remove the leading underscore from your property names, this would work without annotations. Also, Jackson will default to using public fields and getter/setter methods. This means that you can keep your fields prefixed by _ as long as the getter/setter don't have it ( setFirstName(String firstName) ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM