【问题标题】:How to read JSON in list of generic如何在通用列表中读取 JSON
【发布时间】:2019-08-27 14:09:37
【问题描述】:

我有一个帮助类调用 REST Web 服务。该帮助程序类从定义为通用“R”的类中的 Web 服务接收信息。我可以轻松地使用 GSON 在 POJO 中读取我的 JSON,但我不知道如何给它一个 List 并正确读取它。

到目前为止,我已经尝试在变量中提取 R 的类型并将其传递给 List,但没有成功。我曾尝试将 Jackson 与它的 TypeFactory 一起使用,但也没有成功,它不会将 R 作为其参数。

我想做的是这样的:

resource = new GsonBuilder().create().fromJson(response,List<R>)

或与杰克逊一起

resource = mapper.readValue(response, List<R>);

“response”是我的 JSON 字符串,资源是我想要返回的 List 的实例。

我可以使用 GSON 或 Jackson。我一直在尝试这两种方法,因为其中一种看起来更有可能。

我能够使其与非泛型一起使用,但我使用泛型得到的只是 JSON 字段的 Map 列表列表。它基本上忽略了R的类型。

另外,R 是从一个名为 BaseResource 的类扩展而来的,所以我知道 R 将始终是 BaseResource 的子级,但我需要的字段在子级中。

奖励:我真正的最终目标是让我的通用 R 成为特定对象的列表。所以如果我可以改为:

resource = new GsonBuilder().create().fromJson(response,R)

并且 R 可以是 BaseResource 或 List。我已经使它适用于 BaseResource,但我需要它以某种方式使其适用于 List,或者通过复制其中的大部分并明确声明它是一个 List 或将 List 传递给 R。

我们当前的解决方法是使用包含列表的包装器:

private class Result{
    private List<BaseResource> result;
}

但我们希望 Web 服务返回列表而不是这样的包装器。

【问题讨论】:

标签: java json generics jackson gson


【解决方案1】:

使用 GSON,您必须实现自己的序列化程序,请参阅:Type Information within serialized JSON using GSON

如果你要使用 Jackson,你可以使用 @JsonTypeInfo 注释来解决这个问题 多态类型:https://www.logicbig.com/tutorials/misc/jackson/jackson-json-type-info-annotation.html

【讨论】:

  • 我认为 Jackson 方式不适用于反序列化。我的列表仍然被反序列化为 Map 的列表,而不是放入正确的对象中(R 是 BaseResource 的实现)。
  • 分享类型注解
【解决方案2】:

如果你使用任何框架没有阅读,如果你使用spring你可以使用restTemplate和Jackson,这是一个调用rest服务的泛型类的示例

private <Q, R> R callGeneric(String url, Q query, Class<R> responseClass) {
    R response = null;
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    HttpEntity<Q> req = new HttpEntity<Q>(query, headers);
    RestTemplate restTemplate = new RestTemplate();
    restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
    ResponseEntity<R> callResult = null;
    try{
        callResult = restTemplate.exchange(url, HttpMethod.POST, req, responseClass);
    }catch(HttpClientErrorException e){
        logger.error(e.getStatusCode());
        logger.error(e.getResponseBodyAsString());
        throw e;
    }
    if (callResult == null) {
        logger.error("callGeneric: No response (void) of the rest service");
        return null;
    }
    response = callResult.getBody();
    if (response == null) {
        logger.error("callGeneric: empty response) ");
        return null;
    }
    return response;
}

public ObjectResponse setCustCommunicationSetup(objectRequest request) {
    String url = restCommunicationHostServer + custCommunicationContext + custCommunicationServiceSetCommunicationSetup;
    logger.debug("callGeneric: "+url);
    return callGeneric(url, request, ObjectResponse.class);
}

【讨论】:

    【解决方案3】:

    描述了一个类似的问题hear也许它仍然会帮助你

    如果要反序列化泛型列表,必须正确创建类型

    public static <T> List<T> deserialize(String json, Class<T> clazz) {
        Type type = TypeToken.getParameterized(List.class,clazz).getType();
        return new Gson().fromJson(json, type);
    }
    

    Type myType = new TypeToken<List<DTO1>>() {}.getType();
    List<DTO1> deserialize = new Gson().fromJson(json, myType);
    

    你的解决方法——对我来说很好


    问题是 T,因为 Java 不知道我的种类并生成 T 的类型

    public static <T> List<T> sec(String json, Class<T> clazz) {
        Type type1 = new TypeToken<List<T>>() {}.getType();
        Type type2 = new TypeToken<List<DTO1>>() {}.getType();
        Type type = TypeToken.getParameterized(List.class, clazz).getType();
    
        System.out.println(type1);   //==>....*List<T>
        System.out.println(type2);   //==>....*List<....DTO1> --> this declaration In Java
        System.out.println(type);    //==>....*List<....DTO1>
        return new Gson().fromJson(json, type);
    }
    

    测试

    这是更多示例以正确运行的测试

    package pl.jac.litsofgeneriric;
    
    import java.lang.reflect.Type;
    import java.util.List;
    import java.util.UUID;
    import org.junit.Assert;
    import org.junit.Test;
    import com.google.gson.Gson;
    import com.google.gson.GsonBuilder;
    import com.google.gson.reflect.TypeToken;
    
    public class DeserializeListGenericTest {
    
        @Test
        public void deserializeDTO1() {
            //given
            String json = "[{\"id\":1,\"name\":\"test1\"},{\"id\":2,\"name\":\"test2\"}]";
            //when
            List<DTO1> deserialize = DeserializeListGeneric.deserialize(json, DTO1.class);
            //then
            Assert.assertEquals("test1", deserialize.get(0).name);
        }
    
        @Test
        public void deserializeDTO2() {
            //given
            String json = "[{\"uuid\":\"97e98a6d-aae8-42cb-8731-013c207ea384\",\"name\":\"testUUID1\"},{\"uuid\":\"36c60080-7bb2-4c71-b4d8-c5a0a5fa47a2\",\"name\":\"testUUID1\"}]";
            //when
            List<DTO2> deserialize = DeserializeListGeneric.deserialize(json, DTO2.class);
            //then
            Assert.assertEquals("testUUID1", deserialize.get(0).name);
        }
    
        @Test
        public void deserializeMyType() {
            //given
            String json = "[{\"id\":1,\"name\":\"test1\"},{\"id\":2,\"name\":\"test2\"}]";
            //when
            Type myType = new TypeToken<List<DTO1>>() {
            }.getType();
            List<DTO1> deserialize = new Gson().fromJson(json, myType);
            //then
            Assert.assertEquals("test1", deserialize.get(0).name);
        }
    
        @Test
        public void deserializeGsonBuilder() {
            //given
            String json = "[{\"id\":1,\"name\":\"test1\"},{\"id\":2,\"name\":\"test2\"}]";
            //when
    
            Type myType = new TypeToken<List<DTO1>>() {
            }.getType();
            List<DTO1> deserialize = new GsonBuilder().create().fromJson(json, myType);
            //then
            Assert.assertEquals("test1", deserialize.get(0).name);
        }
        @Test
        public void useSystemOut() {
            //given
            String json = "[{\"id\":1,\"name\":\"test1\"},{\"id\":2,\"name\":\"test2\"}]";
            //when
            List<DTO1> deserialize = sec(json, DTO1.class);
            //then
            Assert.assertEquals("test1", deserialize.get(0).name);
        }
    
        public static <T> List<T> sec(String json, Class<T> clazz) {
            Type type1 = new TypeToken<List<T>>() {}.getType();
            Type type2 = new TypeToken<List<DTO1>>() {}.getType();
            Type type = TypeToken.getParameterized(List.class, clazz).getType();
    
            System.out.println(type1);   //==>....*List<T>
            System.out.println(type2);   //==>....*List<....DTO1> --> this declaration In Java
            System.out.println(type);    //==>....*List<....DTO1>
            return new Gson().fromJson(json, type);
        }
    
        public static class DTO1 {
    
            public Long id;
            public String name;
        }
    
        public static class DTO2 {
            public UUID uuid;
            public String name;
        }
    }
    

    和类 DeserializeListGeneric

    package pl.jac.litsofgeneriric;
    
    import java.lang.reflect.Type;
    import java.util.List;
    import com.google.gson.Gson;
    import com.google.gson.reflect.TypeToken;
    
    public class DeserializeListGeneric {
    
    
        public static <T> List<T> deserialize(String json, Class<T> clazz) {
            Type type = TypeToken.getParameterized(List.class,clazz).getType();
            return new Gson().fromJson(json, type);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2013-08-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-23
      • 1970-01-01
      • 2020-10-11
      • 2021-03-23
      • 1970-01-01
      相关资源
      最近更新 更多