繁体   English   中英

GSON +从Web服务解析json并获取特定JsonObject的json字符串

[英]GSON + parse json from webservice and get the json string for the particular JsonObject

我有从Web服务读取json的情况。 这个Json是包含大量数据的节点数组

我要实现的目标:

  1. 对于数组中的每个节点,仅读取必需的元素。 使用GSON对象模型完成此操作。
  2. 对于数组中的每个节点,需要该特定节点的Json字符串,并将其作为字符串添加到步骤1的Java对象中。

需要执行步骤2,因为Java impl将调用另一个服务,该服务又需要每个节点的json进行进一步处理。

为了达到这个目的,我尝试了什么:

  1. 使用对象模型为步骤1创建Java对象。
  2. 再次使用带有JsonArray.class的对象模型读取整个json,这会为我提供每个节点的Json字符串(JsonArray.get(i).toString())。
  3. 找到一种匹配Json String和Java对象的方法,可能是使用Node id,这又需要从步骤2中进行解析。

我的问题:

  1. 我使用正确的方法吗? 两次解析Json可以吗? 有没有更好的方法来实现这一目标?
  2. 我并不热衷于使用JsonReader,但这会是一个更好的解决方案吗? 如果可以,如何辩解?

staff.json:

[
{
    "name": "Joe",
    "age" : 35,
    "position": "dev",
    "salary": 10000,
    "skills":[ "angular", "aws", "java"],
    "Organistaion" : "Test",
    "WorkType": "Full-time"
},

{
    "name": "John",
    "age" : 29,
    "position": "dev",
    "salary": 10000,
    "skills":[ "python", "c#", "java"],
    "Organistaion" : "Test",
    "WorkType": "Full-time"
}

]

Staff.java:

public class Staff {
private String name;
private int age;
private String staffJson;
.......

}

StaffSandbox.java:

public class StaffSandbox {
public static void main (String s[]) {
    Gson gson = new Gson();

    try (Reader reader = new FileReader("C:\\staff.json")) { // for sample code use file

        // Step 1
        List<Staff> staffs = gson.fromJson(reader, new TypeToken<List<Staff>>() {}.getType());
        staffs.forEach(System.out::println);

        // Step 2
        String json = new String(Files.readAllBytes(Paths.get(("C:\\staff.json"))));
        JsonArray jsonElement = gson.fromJson(json, JsonArray.class);
        System.out.println( gson.toJson(jsonElement.get(0)).toString());

        // Step 3
        for (int i = 0; i < json.size(); i++) {
            // Read the node Id and match with corresponding Staff object and add the json to it            
        }

    } catch (IOException e) {
        e.printStackTrace();
    }
}

}

我使用正确的方法吗? 两次解析Json可以吗? 有没有更好的方法来实现这一目标?

并不是的。 您可避免读取文件两次+节省大量的存储在你的第二个读:你正在阅读整个文件的字节数组首先转换成字符串转换为JSON阵列。 对大型文件测试此方法,您可能会遇到OutOfMemoryError

我并不热衷于使用JsonReader,但这会是一个更好的解决方案吗? 如果可以,如何辩解?

JsonReader以流式处理的方式标记化JSON输入,并且在许多情况下JsonReader您提供很多帮助。

如果我对您的理解正确,那么您只需要以下内容:

private static void zip(final Gson gson, final Reader reader, final Consumer<? super JsonObject> consumer)
        throws IOException {
    // The next two lines request some stuff from the given Gson instance
    final TypeAdapter<JsonObject> jsonObjectTypeAdapter = gson.getAdapter(JsonObject.class);
    final JsonReader jsonReader = gson.newJsonReader(reader);
    // Ensure that the very first token is array begin `[`
    jsonReader.beginArray();
    // And read all the array elements
    while ( jsonReader.hasNext() ) {
        // JsonReader does not consume entire input stream and can read necessary JSON token only
        final JsonObject incomingJsonObject = jsonObjectTypeAdapter.read(jsonReader);
        // And this is what we generate
        final JsonObject outgoingJsonObject = new JsonObject();
        outgoingJsonObject.add("name", incomingJsonObject.get("name"));
        outgoingJsonObject.add("age", incomingJsonObject.get("age"));
        outgoingJsonObject.add("staffJson", new JsonPrimitive(incomingJsonObject.toString()));
        // Once a "staff row" is ready to use, just delegate it elsewhere
        consumer.accept(outgoingJsonObject);
    }
    jsonReader.endArray();
}

请注意,上面的示例未使用与Staff一样的Java映射。 如果需要,可以使用Gson.toJsonTree()Gson.fromJson()JsonElement转换为Java映射,反之亦然。 此外,您甚至可以直接将输出写入指定的JsonWriter甚至不创建outgoingJsonObject实例(简单的R / W管道:从输入读取==>处理==>写入输出)。

使用示例(请注意,不能两次或多次使用Reader ;使用方实现使用不同的策略:将每个新生成的JsonObject直接刷新到System.out (您可以处理非常大的数据集);或将所有此类对象收集到列出,然后做任何您想做的事情(集合必须容纳在内存中):

try ( final Reader reader = getPackageResourceReader(Q43105667.class, "staff.json") ) {
    zip(gson, reader, System.out::println);
}
try ( final Reader reader = getPackageResourceReader(Q43105667.class, "staff.json") ) {
    final Collection<JsonObject> list = new ArrayList<>();
    zip(gson, reader, list::add);
    System.out.println(list);
}

{ “名”: “乔”, “年龄”:35, “staffJson”: “{\\” 名称\\ “:\\” 乔\\ “\\ ”年龄\\“:35 \\ ”位置\\“:\\” 开发\\”,\\ “薪水\\”:10000,\\ “技能\\”:[\\ “角\\”,\\ “AWS \\” \\ “的java \\”],\\ “Organistaion \\”:\\ “测试\\”,\\ “WorkType \\”:\\ “全职\\”}“
{ “名”: “约翰”, “年龄”:29, “staffJson”: “{\\” 名称\\ “:\\” 约翰\\ “\\ ”年龄\\“:29 \\ ”位置\\“:\\” 开发\\”,\\ “工资\\”:10000,\\ “技能\\”:\\ “蟒蛇\\”,\\ “C#\\”,\\ “的java \\”] \\ “Organistaion \\”:\\ “测试\\”,\\ “WorkType \\”:\\ “全职\\”}“
[{ “名称”: “乔”, “年龄”:35, “staffJson”: “{\\” 名称\\ “:\\” 乔\\ “\\ ”年龄\\“:35,\\ ”位置\\“:\\” dev的\\”,\\ “薪水\\”:10000,\\ “技能\\”:[\\ “角\\”,\\ “AWS \\” \\ “的java \\”],\\ “Organistaion \\”:\\ “测试\\”, \\“ WorkType \\”:\\“全职\\”}“},{” name“:” John“,” age“:29,” staffJson“:” {\\“ name \\”:\\“ John \\”, \\ “年龄\\”:29 \\ “位置\\”:\\ “开发\\”,\\ “工资\\”:10000,\\ “技能\\”:\\ “蟒蛇\\”,\\ “C#\\”,\\“的java \\ “] \\” Organistaion \\ “:\\” 测试\\ “\\ ”WorkType \\“:\\ ”全职\\“}”}]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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