【问题标题】:Spring boot Gson custom serializationSpring boot Gson 自定义序列化
【发布时间】:2020-03-03 13:19:43
【问题描述】:

我正在尝试将我的 sprin boot 应用程序中的 JSON 序列化从默认的 Jackson 移动到 Gson。我在 pom.xml 和 application.properties 中的以下属性中添加了托管依赖项

spring.http.converters.preferred-json-mapper=gson
spring.gson.enable-complex-map-key-serialization=true

被序列化的 POJO 具有导致以下错误的 BigDecimal 字段。提供类型适配器的正确方法是什么。

Caused by: java.lang.UnsupportedOperationException: Attempted to serialize java.lang.Class: java.math.BigDecimal. Forgot to register a type adapter? at com.google.gson.internal.bind.TypeAdapters$1.write(TypeAdapters.java:73) ~[gson-2.8.5.jar:na] at com.google.gson.internal.bind.TypeAdapters$1.write(TypeAdapters.java:69) ~[gson-2.8.5.jar:na] at com.google.gson.TypeAdapter$1.write(TypeAdapter.java:191) ~[gson-2.8.5.jar:na] at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69) ~[gson-2.8.5.jar:na] at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:127) ~[gson-2.8.5.jar:na] at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:245) ~[gson-2.8.5.jar:na] at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69) ~[gson-2.8.5.jar:na] at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:97) ~[gson-2.8.5.jar:na] at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:61) ~[gson-2.8.5.jar:na] at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69) ~[gson-2.8.5.jar:na] at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:127) ~[gson-2.8.5.jar:na] at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:245) ~[gson-2.8.5.jar:na] at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69) ~[gson-2.8.5.jar:na] at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:127) ~[gson-2.8.5.jar:na] at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:245) ~[gson-2.8.5.jar:na] at com.google.gson.Gson.toJson(Gson.java:704) ~[gson-2.8.5.jar:na] at com.google.gson.Gson.toJson(Gson.java:683) ~[gson-2.8.5.jar:na] at com.google.gson.Gson.toJson(Gson.java:658) ~[gson-2.8.5.jar:na] at org.springframework.http.converter.json.GsonHttpMessageConverter.writeInternal(GsonHttpMessageConverter.java:106) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE] at org.springframework.http.converter.json.AbstractJsonHttpMessageConverter.writeInternal(AbstractJsonHttpMessageConverter.java:125) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE] ... 61 common frames omitted

【问题讨论】:

  • 能否请您发布您的 POJO。
  • 请分享您的代码

标签: spring-boot gson


【解决方案1】:

我已经解决了这个问题。默认情况下似乎不支持“Class”类,因此我们需要注册一个类型适配器,如下所示。

解决方案

@Configuration
@ConditionalOnClass(Gson.class)
public class GsonConfig {
@Bean
public Gson gson() {
    return new GsonBuilder().registerTypeHierarchyAdapter(Class.class, new 
TypeAdapter<Class>() {
        @Override
        public void write(JsonWriter out, Class value) throws IOException {
            out.value(value.getName());
        }

        @Override
        public Class read(JsonReader in) throws IOException {
            try {
                return Class.forName(in.nextString());
            } catch (ClassNotFoundException e) {
                throw new IOException(e);
            }
        }
    }.nullSafe()).create();
   }
  }

【讨论】:

    【解决方案2】:

    下面是处理方法

    @GetMapping(path = "/accounts", produces = "application/json")
    public OutputParam getAccount(
            @RequestParam String refNum) {
    
        return service.getAccount(refNum);
    }
    

    在导致问题的 POJO 下方。它嵌套在输出 POJO 中。这里有一个导致问题的 BigDecimal 类。

    public class Column implements Serializable {
    private static final long serialVersionUID = 1L;
    
    private final String code;
    private final Class<?> dataType;
    
    public CIMColumn(String code, Class<?> dataType) {
        this.code = code;
        this.dataType = dataType;
    }
    
    public String getCode() {
        return code;
    }
    
    public Class<?> getType() {
        return dataType;
    }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-30
      • 1970-01-01
      • 1970-01-01
      • 2016-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多