【问题标题】:Parsing JSON data into model objects in Java在 Java 中将 JSON 数据解析为模型对象
【发布时间】:2016-07-17 10:17:30
【问题描述】:

我以前没有使用过 JSON 数据,因此提出了这个问题。 我在一个文件中有以下 JSON 对象。

{
    "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"}    
    ]
}

这是我的模型对象。

public class Course {

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

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

我的任务是读取 JSON 对象并返回模型对象列表。

我已经导入了 jar 的 simple.JSON 系列,这是我读取文件的代码。

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

    JSONObject jsonObject = (JSONObject) obj;

我的问题是,

  1. 如何将 JSON 文档解析为模型对象?
  2. 如果输入文件是 JSON 但格式不同,我该如何抛出异常/处理异常?

任何帮助表示赞赏。

【问题讨论】:

标签: java json


【解决方案1】:

UPDATE我建议你使用JSON解析器来解析数据:

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;
    }

}

输出:

顺便说一句:示例中的json数据有一个值,其双引号不是成对的。要继续,它必须被修复。

【讨论】:

  • 您从哪个链接下载了简单的 JSON 库。我似乎缺少 JSONException。
  • 请试试这个URL
  • 这真的很有帮助,还有一个问题,有没有办法在使用之前检查密钥是否存在。
  • JSONObject 类有一个名为“has”的方法。请查收:stackoverflow.com/questions/17487205/…
  • 我可以从 java.nio 传递一个路径对象,而不是字符串 JSON_DATA。因为当我这样做时,我会得到org.json.JSONException: JSONObject["teachers"] not found
【解决方案2】:

您应该尝试使用 Jackson 作为 JSON 解析库。它附带了更多的支持和功能。

在您的情况下,将 JSON 属性映射到 Java 字段的几个注释就足够了。

更新:一些代码,为了更好地展示这可以用 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);

@JsonProperty 注释告诉杰克逊应该使用什么 JSON 密钥来反序列化。如果属性名称与 JSON 键匹配,则它们不是必需的。这意味着如果您从属性名称中删除前导下划线,这将在没有注释的情况下工作。此外,Jackson 将默认使用公共字段和 getter/setter 方法。这意味着只要 getter/setter 没有前缀 (setFirstName(String firstName)),您就可以保留以 _ 为前缀的字段。

【讨论】:

  • 这远不是一个答案。您刚刚提供了库。他说他以前没有使用过json。所以,他需要了解它的基础知识。请提供更多解释并显示一些代码 sn-ps 以说明他/她如何处理他提供的 json。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-24
相关资源
最近更新 更多