GVKun编程网logo

如何使用Java Gson库转换动态JSON响应(gson json转对象)

5

以上就是给各位分享如何使用JavaGson库转换动态JSON响应,其中也会对gsonjson转对象进行解释,同时本文还将给你拓展Android–RetrofitGson-如何在JSON响应中将JSON

以上就是给各位分享如何使用Java Gson库转换动态JSON响应,其中也会对gson json转对象进行解释,同时本文还将给你拓展Android – Retrofit Gson-如何在JSON响应中将JSON字符串解析为JSON键的对象?、java – GSON解析动态JSON字段、java – 如何使用GSON / JSON将字符串数组转换为对象?、Java 下的 JSON库性能比较:JSON.simple vs. GSON vs. Jackson等相关知识,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!

本文目录一览:

如何使用Java Gson库转换动态JSON响应(gson json转对象)

如何使用Java Gson库转换动态JSON响应(gson json转对象)

我有一个可以返回JSON数组或对象的API。JSON对象示例

{  "id": 1,  "name": "name"}

JSON数组:

[   {       "id": 1,       "name": "name"   },   {       "id": 1,       "name": "name"   }]

将JSON对象响应映射到POJO时,我使用:

MyEntity myEntity = new Gson().fromJson(jsonString, MyEntity.class);

当将JSON数组响应映射到POJO数组时,我使用:

MyEntity[] myEntity = new GSON().fromJson(jsonString, MyEntity[].class);

如何将这两个响应动态转换为适当的类型?

注意:我无法修改服务器响应,这是一个公共API。

谢谢!

编辑:

我正在尝试实现一种自动执行此操作的方法,但是我缺少了一些东西。方法

public <T> T convertResponseToEntity(Class<T> classOfT){    JsonElement jsonElement =  this.gson.fromJson(getResponseAsString(), JsonElement.class);    if (jsonElement.isJsonArray()) {       Type listType = new TypeToken<T>(){}.getType();       return this.gson.fromJson(getResponseAsString(), listType);    }    return this.gson.fromJson(getResponseAsString(), (Type) classOfT);}

它返回LinkedTreeMaps 的列表。如何修改代码以返回与之相同的内容Object[]

答案1

小编典典

如何将这两个响应动态转换为适当的类型?

这取决于如何在此处解释“适当的类型”,因为instanceof一旦您每次需要处理从JSON解析的对象时,它都会导致或访问者模式获得适当的类型。如果您无法更改API,则可以简化其使用方式。这里可能的选项之一是像对待所有内容一样处理此类响应。甚至单个对象也可以仅作为一个元素处理为列表(许多库仅使用具有以下事实的序列/列表进行处理:Java中的Stream
API,.NET中的LINQ,JavaScript中的jQuery等)。

假设您具有以下MyEntity类来处理从所需的API获得的元素:

// For the testing purposes, package-visible final fields are perfect// Gson can deal with final fields toofinal class MyEntity {    final int id = Integer.valueOf(0); // not letting javac to inline 0 since it''s primitive    final String name = null;    @Override    public String toString() {        return id + "=>" + name;    }}

接下来,让我们创建一个类型适配器,该适配器将始终将“ true”列表和单个对象对齐,就好像它是列表一样:

final class AlwaysListTypeAdapter<T>        extends TypeAdapter<List<T>> {    private final TypeAdapter<T> elementTypeAdapter;    private AlwaysListTypeAdapter(final TypeAdapter<T> elementTypeAdapter) {        this.elementTypeAdapter = elementTypeAdapter;    }    static <T> TypeAdapter<List<T>> getAlwaysListTypeAdapter(final TypeAdapter<T> elementTypeAdapter) {        return new AlwaysListTypeAdapter<>(elementTypeAdapter);    }    @Override    @SuppressWarnings("resource")    public void write(final JsonWriter out, final List<T> list)            throws IOException {        if ( list == null ) {            out.nullValue();        } else {            switch ( list.size() ) {            case 0:                out.beginArray();                out.endArray();                break;            case 1:                elementTypeAdapter.write(out, list.iterator().next());                break;            default:                out.beginArray();                for ( final T element : list ) {                    elementTypeAdapter.write(out, element);                }                out.endArray();                break;            }        }    }    @Override    public List<T> read(final JsonReader in)            throws IOException {        final JsonToken token = in.peek();        switch ( token ) {        case BEGIN_ARRAY:            final List<T> list = new ArrayList<>();            in.beginArray();            while ( in.peek() != END_ARRAY ) {                list.add(elementTypeAdapter.read(in));            }            in.endArray();            return unmodifiableList(list);        case BEGIN_OBJECT:            return singletonList(elementTypeAdapter.read(in));        case NULL:            return null;        case END_ARRAY:        case END_OBJECT:        case NAME:        case STRING:        case NUMBER:        case BOOLEAN:        case END_DOCUMENT:            throw new MalformedJsonException("Unexpected token: " + token);        default:            // A guard case: what if Gson would add another token someday?            throw new AssertionError("Must never happen: " + token);        }    }}

Gson
TypeAdapter被设计为以流方式工作,因此从效率角度来看它们很便宜,但实施起来并不那么容易。write()上面的方法只是为了不放在thrownewUnsupportedOperationException();那儿而实现的(我假设您只阅读了该API,但是不知道该API是否会消耗“元素或列表”修改请求)。现在有必要创建一个类型适配器工厂,以让Gson为每种特定类型选择合适的类型适配器:

final class AlwaysListTypeAdapterFactory        implements TypeAdapterFactory {    private static final TypeAdapterFactory alwaysListTypeAdapterFactory = new AlwaysListTypeAdapterFactory();    private AlwaysListTypeAdapterFactory() {    }    static TypeAdapterFactory getAlwaysListTypeAdapterFactory() {        return alwaysListTypeAdapterFactory;    }    @Override    public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken)            throws IllegalArgumentException {        if ( List.class.isAssignableFrom(typeToken.getRawType()) ) {            final Type elementType = getElementType(typeToken);            // Class<T> instances can be compared with ==            final TypeAdapter<?> elementTypeAdapter = elementType == MyEntity.class ? gson.getAdapter(MyEntity.class) : null;            // Found supported element type adapter?            if ( elementTypeAdapter != null ) {                @SuppressWarnings("unchecked")                final TypeAdapter<T> castTypeAdapter = (TypeAdapter<T>) getAlwaysListTypeAdapter(elementTypeAdapter);                return castTypeAdapter;            }        }        // Not a type that can be handled? Let Gson pick a more appropriate one itself        return null;    }    // Attempt to detect the list element type      private static Type getElementType(final TypeToken<?> typeToken) {        final Type listType = typeToken.getType();        return listType instanceof ParameterizedType                ? ((ParameterizedType) listType).getActualTypeArguments()[0]                : Object.class;    }}

以及如何使用它:

private static final Type responseItemListType = new TypeToken<List<MyEntity>>() {}.getType();private static final Gson gson = new GsonBuilder()        .registerTypeAdapterFactory(getAlwaysListTypeAdapterFactory())        .create();public static void main(final String... args) {    test("");    test("{\"id\":1,\"name\":\"name\"}");    test("[{\"id\":1,\"name\":\"name\"},{\"id\":1,\"name\":\"name\"}]");    test("[]");}private static void test(final String incomingJson) {    final List<MyEntity> list = gson.fromJson(incomingJson, responseItemListType);    System.out.print("LIST=");    System.out.println(list);    System.out.print("JSON=");    gson.toJson(list, responseItemListType, System.out); // no need to create an intermediate string, let it just stream    System.out.println();    System.out.println("-----------------------------------");}

输出:

LIST=nullJSON=null-----------------------------------LIST=[1=>name]JSON={"id":1,"name":"name"}-----------------------------------LIST=[1=>name, 1=>name]JSON=[{"id":1,"name":"name"},{"id":1,"name":"name"}]-----------------------------------LIST=[]JSON=[]-----------------------------------

Android – Retrofit Gson-如何在JSON响应中将JSON字符串解析为JSON键的对象?

Android – Retrofit Gson-如何在JSON响应中将JSON字符串解析为JSON键的对象?

这是我的 JSON响应:

{
      "id": 2,"name": "Test","content": "{\"type\": \"status\",\"text\": \"Lorem ipsum dummy text.\",\"id\": 1}"
}

这些是模型结构:

class TestModel {
    public int id;
    public String name;
    public Content content;
}

class Content {
    public int id;
    public String status;
    public String text;
}

我想使用Retrofit和GsonConvertor将内容的值直接解析到我的Content模型对象中.但是目前,我将其解析为String值,而不是使用Gson.fromJson()转换为我的Content模型对象.是否有任何解决方案可以获得我的预期结果?

当我以前使用GsonConverterFactory解析它时,Retrofit在onFailure方法中给出了回调,但有以下异常:

java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 4 column 19 path $.data[0].content

解决方法

问题在于JSON响应,它不在 correct JSON format中.“content”字段应该是一个对象,而不是一个字符串:

{
    "id": 2,"content": {
        "type": "status","text": "Lorem ipsum dummy text.","id": 1
    }
}

这将允许gson.fromJson(response,TestModel.class)或带有GsonConverterFactory的RetroFit将您的响应正确解析为相应的对象.

当然,这仅适用于您能够更改正在接收的JSON响应的情况.如果没有,首先要确保控制响应的人知道他们做错了.如果没有任何变化,那么您应该能够通过将TestModel中的内容更改为String来解决此问题:

class TestModel {
    public int id;
    public String name;
    public String content;
}

class Content {
    public int id;
    public String type;
    public String text;
}

然后分别解析每个对象:

TestModel testModel = gson.fromJson(response,TestModel.class);
Content content = gson.fromJson(testModel.content,Content.class);

如果无法更改响应,则另一个选项是为Content对象创建TypeAdapter

public class ContentAdapter extends TypeAdapter<Content> {

    @Override
    public void write(JsonWriter out,Content value) throws IOException {
        // Todo: Writer implementation
    }

    @Override
    public Content read(JsonReader in) throws IOException {
        if(in.peek() != JsonToken.NULL) {
            return fromJson(in.nextString());
        } else {
            in.nextNull();
            return null;
        }
    }

}

然后将TypeAdapter添加到您的GSON实现:

Gson gson = new GsonBuilder()
        .registerTypeAdapter(Content.class,new ContentAdapter()).create();

java – GSON解析动态JSON字段

java – GSON解析动态JSON字段

我似乎无法弄清楚这一点.我看了几个SO帖子( here和 here),我的情况有点不同.

我不确定我是否必须注册一个新的Typetoken或什么.但我的JSON对象如下所示:

{
    "id": 6,"error": "0","dates": {
        34234 : "2011-01-01" // I want to parse the date into a string.
        87474 : "2011-08-09" // The first values are all unique.
        .                    //this can be any number of entries.
        .
        .
        74857 : "2011-09-22"
    }
}

我创建了两个像这样的对象:

public class Response {

    public Integer id;
    public String error;
    public DateList dates;
}

单独的文件:

public class DateList {

    public List<Map<Integer,String>> dateString;
}

我不确定如何调整它以使其正确.文档似乎没有帮助…我见过的其他示例是解析自定义对象,而不是字符串类型.

谢谢!

解决方法

我试过这种形式:

杰森

{
    "id": 6,"dates": {
        "34234" : "2011-01-01"
        "87474" : "2011-08-09"
        "74857" : "2011-09-22"
    }
}

和Response.java

public class Response {
    public Integer id;
    public String error;
    public Map<Integer,String> dates;
}

至少那似乎是开箱即用的.

java – 如何使用GSON / JSON将字符串数组转换为对象?

java – 如何使用GSON / JSON将字符串数组转换为对象?

我有一个像这样的json:
[
  [
    "Passport Number","NATIONALITY","REASONS"
  ],[
    "SHAIS100","INDIA",""
  ],[
    "","","Agent ID is not matched."
  ],""
  ]
]

我想将其填充到ArrayList< String []>,请告诉我该怎么办?

空字符串不应转换为空.

解决方法

这很简单,您只需要执行以下操作:

1.-首先创建Gson对象:

Gson gson = new Gson();

2.-然后获取您的列表的通讯录类型< String []> (请注意,由于Java的type erasure,您无法像List< String []> .class这样做):

Type type = new Typetoken<List<String[]>>() {}.getType();

3.-最后将JSON解析为类型类型的结构:

List<String[]> yourList = gson.fromJson(yourjsonString,type);

Java 下的 JSON库性能比较:JSON.simple vs. GSON vs. Jackson

Java 下的 JSON库性能比较:JSON.simple vs. GSON vs. Jackson

 JSON已经成为当前服务器与WEB应用之间数据传输的公认标准,不过正如许多我们所习以为常的事情一样,你会觉得这是理所当然的便不再深入思考了。我们很少会去想用到的这些JSON库到底有什么不同,但事实上它们的确是不太一样的。因此,我们运行了一个基准测试来对常用的几个JSON库进行了测试,看看在解析不同大小的文件时哪个库的速度是最快的。下面我会把结果分享给大家。

Java 下的 JSON库性能比较:JSON.simple vs. GSON vs. Jackson vs. JSONP

  JSON通常用于传输及解析大文件。这对运行在Hadoop或者是Spark集群上的数据处理程序而言是个很常见的场景。在给定的文件大小下,你可以看到不同库之间的解析速度存在着明显的差别。

  高吞吐量的情况下,会频繁地传输并解析小文件,因此一开始的时候可能性能的差距并不明显。但如果你需要在非常高负载下频繁地解析大量的小文件,差距就开始增大了。微服务及分布式架构经常会使用JSON来传输此类文件,因为这已经是WEB API的事实标准。

  不是所有的JSON库都叫”特仑苏”。如何根据使用场景才选择正确的库是相当重要的。希望这个基准测试能够对你有所帮助。

 JSON.simple vs GSON vs Jackson vs JSONP

  我们选择了四个主流的JSON库来进行基准测试:JSON.simple, GSON, Jackson以及JSONP。在Java中进行JSON解析通常都会用到这几个库,选择它们的原因是它们在Github项目中的亮相频率很高。

  下面便是我们所测试的JSON库:

  • Yidong Fang的JSON.simple(https://github.com/fangyidong/json-simple)。JSON.simple是一个JSON编解码的Java工具库。它旨在打造一个轻量简单且高性能的工具库。
  • Google的GSON(https://github.com/google/gson)。GSON这个Java库能够在Java对象和JSON间进行相互转换。同时它还提供了对Java泛型的完整支持,而且还不需要你在类上面添加注解。无需添加注解使用起来则更为便捷,同时在无法修改源代码的情况下这还是一个必要的先决条件。
  • FasterXML的Jackson项目(https://github.com/FasterXML/jackson)。Jackson是一个数据处理的工具套件,它的亮点是流式的JSON解析器及生成器。它是专为Java设计的,同时也能处理其它非JSON的编码。从我们在Github中的统计来看,它应该是最流行的JSON解析器。
  • Oracle的JSONP(https://jsonp.java.net/)。JSONP (JSON Processing)是JSON处理的一套Java API,从名字来看它就是用来生成及解析JSON串的。这是JSR353规范的一个开源实现。

 基准测试

  我们同时使用大文件和小文件对这些库进行了基准测试。随着文件大小的不同,处理这些文本所需要的系统资源也会随之上升。

  这个基准测试主要关注两个关键场景:大文件下(190MB)的解析速度与小文件(1KB)下的解析速度。大文件取自这里:https://github.com/zeMirco/sf-city-lots-json。小文件是从这里随机生成的:http://www.json-generator.com/。

  不管是大文件还是小文件,我们都会用同一个库重复运行10次。对于每一个大文件,我们都会用同一个库来分别运行10次。而对于小文件,在单个库的单次运行中会重复执行10000次。在小文件测试的各次迭代中,文件内容都不会驻留在内存里,测试所运行的机器是AWS的c3.large实例。

  大文件的完整测试结果如下,我对小文件的结果求了个平均值。想要看完整的结果,请移步这里。如果想看小文件测试的源码,请从这里下载。

 大文件结果

Java 下的 JSON库性能比较:JSON.simple vs. GSON vs. Jackson vs. JSONP

  结果相差甚大!Jackson与JSON.simple领跑了这轮测试,整体来看Jackson又要略优于JSON.simple。从测试运行的平均结果来看,Jackson与JSON.simple在大文件上的表现要优秀一些,而JSONP排名第三落后甚远,GSON更是遥遥垫底。

  我们再把结果换算成百分比看下。平均来看Jackson要胜出一筹。下面是结果的百分比数据,可以从两个维度来进行比较:

Java 下的 JSON库性能比较:JSON.simple vs. GSON vs. Jackson vs. JSONP

  不同库之间的性能差别着实不小。

  结论:Jackson以略微优势胜出。JSON.simple紧随其后,而剩下两个库则远远落后。

 小文件结果

Java 下的 JSON库性能比较:JSON.simple vs. GSON vs. Jackson vs. JSONP

  上表记录的是对每个文件解析10次的平均时间,总的平均时间见下方。各个库在小文件测试中夺冠的次数如下:

  • GSON – 14
  • JSONP – 5
  • Jackson -1
  • JSON.simple – 0

  这个结果貌似很有说服力。然而,从所有文件的平均结果来看,GSON这个冠军还是当之无愧的,JSON.simple和JSONP的二三名之争应该没什么悬念。Jackson这轮却是垫底了。尽管JSON.simple没有在任何文件上夺得第一,但总体来看它的解析速度却是排名第二位的。而JSONP尽管在许多文件上都拿到了冠军,但平均来看却只拿到了第三名的成绩。

  还有一个值得注意的是,尽管Jackson是这轮最慢的库,但是它在所有文件中的表现都非常一致,其它三个库虽然偶然会比Jackson快很多,但在另一些文件上的解析速度却是旗鼓相当甚至更差。

  我们再把这些数字转换成百分比看看,还是同样的两个维度:

Java 下的 JSON库性能比较:JSON.simple vs. GSON vs. Jackson vs. JSONP

  和大文件测试相比,这次的差距相对要小一些,但也还是不容忽视的。

  结论:很不幸的是,JSON.simple又以微弱的劣势与冠军失之交臂,这轮GSON胜。JSONP仍是千年老三而这回Jackson则赶了个晚集。

 总结

  解析速度并非衡量一个JSON库的唯一指标,但它的确非常重要。通过运行这次基准测试,我们发现没有一个库能在所有文件上击败对手。大文件中表现优秀的却在小文件上栽了根头,反之亦然。

  如果要从解析速度来看选择哪个库的话还得取决于你的使用场景。

  • 如果你的应用经常会处理大的JSON文件,那么Jackson应该是你的菜。GSON在大文件上表现得相当吃力。
  • 如果你主要是处理小文件请求,比如某个微服务或者分布式架构的初始化,那么GSON当是首选。Jackson在小文件上的表现则不如人意。
  • 如果这两种文件你都经常会处理到,那么在两轮表现中都位居第二的JSON.simple对此类场景则更为适合。在不同的文件大小上Jackson和GSON的表现都不太好。

  除非不考虑解析速度,不然JSONP完全没有什么值得称道的。它在大文件和小文件上的表现与其它库相比都很糟糕。所幸的是,Java 9很快便会有原生的JSON实现了,相信JSONP将来的表现仍然值得期待。

  终于讲完了。如果你对JSON库的解析速度比较敏感的话,大文件选Jackson,小文件选GSON,两者则JSON.simple。

今天关于如何使用Java Gson库转换动态JSON响应gson json转对象的介绍到此结束,谢谢您的阅读,有关Android – Retrofit Gson-如何在JSON响应中将JSON字符串解析为JSON键的对象?、java – GSON解析动态JSON字段、java – 如何使用GSON / JSON将字符串数组转换为对象?、Java 下的 JSON库性能比较:JSON.simple vs. GSON vs. Jackson等更多相关知识的信息可以在本站进行查询。

本文标签: