Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Json 用于带有枚举键的映射的GSON自定义序列化程序_Json_Spring_Serialization_Gson - Fatal编程技术网

Json 用于带有枚举键的映射的GSON自定义序列化程序

Json 用于带有枚举键的映射的GSON自定义序列化程序,json,spring,serialization,gson,Json,Spring,Serialization,Gson,我正在序列化的对象包含一个映射,该映射的键是枚举。这些枚举有一个变量。当我用GSON序列化它时,我希望得到的JSON使用Enum变量而不是默认的Enum名称。我曾尝试创建一个自定义序列化程序并注册它,但它没有起到作用。这是我的密码 控制员: @Controller public class CheckoutClientController { @Autowired private Gson gson; @Autowired private RequestHelper requestHelper

我正在序列化的对象包含一个映射,该映射的键是枚举。这些枚举有一个变量。当我用GSON序列化它时,我希望得到的JSON使用Enum变量而不是默认的Enum名称。我曾尝试创建一个自定义序列化程序并注册它,但它没有起到作用。这是我的密码

控制员:

@Controller
public class CheckoutClientController {

@Autowired
private Gson gson;
@Autowired
private RequestHelper requestHelper;
@Autowired
private SettingsReader settingsReader;

@InitBinder
public void initBinder(final WebDataBinder binder) {
    binder.registerCustomEditor(CheckoutConfigurationDto.class, new JsonDeserializerPropertyEditor<CheckoutConfigurationDto>(gson, CheckoutConfigurationDto.class));
}

/**
 * Handles requests to the Checkout Client page, which is the outer wrapper that includes the white label checkout (WLC) iframe. Sets up the configuration
 * data needed to pass to the WLC server.
 * 
 * @return the model and view
 */
@RequestMapping(value = "/checkout/checkout-client.ep", method = RequestMethod.GET)
public ModelAndView showPage(HttpServletRequest request) {
    CheckoutClientConfigurationDto checkoutClientConfig = new CheckoutClientConfigurationDto();

    StringBuilder host = new StringBuilder();
    host.append(request.getScheme()).append("://");
    host.append(request.getServerName());
    host.append(":").append(request.getServerPort());

    checkoutClientConfig.setWlcHost(host.toString());
    checkoutClientConfig.setClientId("clientId");
    checkoutClientConfig.setAppId("appId");
    checkoutClientConfig.setId("wlc-widget");

    Map<CheckoutClientConfigurationOption, Boolean> options = checkoutClientConfig.getOptions();

    options.put(CheckoutClientConfigurationOption.SHOW_ORDER_CONFIRMATION,
            Boolean.valueOf(this.settingsReader.getSettingValue(SettingsConstants.SHOW_ORDER_CONFIRMATION).getValue()));
    options.put(CheckoutClientConfigurationOption.REMOVE_CART_ITEMS,
            Boolean.valueOf(this.settingsReader.getSettingValue(SettingsConstants.REMOVE_CART_ITEMS).getValue()));

    return new ModelAndView(ViewConstants.CHECKOUT_CLIENT_TEMPLATE_PATH, "checkoutClientConfig", gson.toJson(checkoutClientConfig));
}
}
我的自定义GSON序列化程序:

public class CheckoutClientConfigurationOptionGsonSerializer implements JsonSerializer<CheckoutClientConfigurationOption> {

@Override
public JsonElement serialize(CheckoutClientConfigurationOption src, Type typeOfSrc, JsonSerializationContext context) {
    return new JsonPrimitive(src.getOptionName());
}

}
公共类checkoutclientconfigurationoptionsonSerializer实现JsonSerializer{
@凌驾
公共JsonElement序列化(CheckoutClientConfigurationOption src,类型typeOfSrc,JsonSerializationContext){
返回新的JsonPrimitive(src.getOptionName());
}
}
我的自定义GSON配置程序:

public class GsonConfigurer {

private Map<Class<?>, Object> typeAdapterMap;

public Gson create() {
    final GsonBuilder gsonBuilder = new GsonBuilder();

    for (final Entry<Class<?>, Object> typeAdapterMapping : typeAdapterMap.entrySet()) {
        gsonBuilder.registerTypeAdapter(typeAdapterMapping.getKey(), typeAdapterMapping.getValue());
    }

    return gsonBuilder.create();
}

protected Map<Class<?>, Object> getTypeAdapterMap() {
    return typeAdapterMap;
}

public void setTypeAdapterMap(final Map<Class<?>, Object> typeAdapterMap) {
    this.typeAdapterMap = typeAdapterMap;
}

}
公共类GSONConfigure{
私有映射,对象>getTypeAdapterMap(){
返回类型适配器映射;
}

public void setTypeAdapterMap(final Map您应该好好学习一下。它包括一个将枚举格式化为小写的示例;您可以根据自己的需要修改它

public class LowercaseEnumTypeAdapterFactory implements TypeAdapter.Factory {
  public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
    Class<T> rawType = (Class<T>) type.getRawType();
    if (!rawType.isEnum()) {
      return null;
    }

    final Map<String, T> lowercaseToConstant = new HashMap<String, T>();
    for (T constant : rawType.getEnumConstants()) {
      lowercaseToConstant.put(toLowercase(constant), constant);
    }

    return new TypeAdapter<T>() {
      public void write(JsonWriter out, T value) throws IOException {
        if (value == null) {
          out.nullValue();
        } else {
          out.value(toLowercase(value));
        }
      }

      public T read(JsonReader reader) throws IOException {
        if (reader.peek() == JsonToken.NULL) {
          reader.nextNull();
          return null;
        } else {
          return lowercaseToConstant.get(reader.nextString());
        }
      }
    };
  }

  private String toLowercase(Object o) {
    return o.toString().toLowerCase(Locale.US);
  }
}
公共类LowercaseEnumTypeAdapterFactory实现TypeAdapter.Factory{
公共类型适配器创建(Gson Gson,TypeToken类型){
类rawType=(类)type.getRawType();
如果(!rawType.isEnum()){
返回null;
}
final Map lowercaseToConstant=新HashMap();
对于(T常量:rawType.getEnumConstants()){
lowercasetoctant.put(toLowercase(constant),constant);
}
返回新的TypeAdapter(){
public void write(JsonWriter out,T值)抛出IOException{
如果(值==null){
out.nullValue();
}否则{
out.value(toLowercase(value));
}
}
公共T读取(JsonReader读取器)引发IOException{
if(reader.peek()==JsonToken.NULL){
reader.nextNull();
返回null;
}否则{
返回LowercaseToctant.get(reader.nextString());
}
}
};
}
私有字符串toLowercase(对象o){
返回o.toString().toLowerCase(Locale.US);
}
}

阅读有关的文档时,我发现:

映射序列化的默认实现在键上使用toString()


因此,默认情况下,它不会在映射键上运行
TypeAdapter
。我尝试简单地调用此方法,并使我的枚举显示为数字字符串。

我尝试了此方法,但得到了几乎相同的结果。我发现问题在于,我的枚举是作为映射键嵌入的。它将枚举序列化为小写,不带任何字符如果我将它作为DTO中的单个变量,但当我将它用作映射的键时,它不会调用我的自定义序列化程序或自定义类型适配器。我也有同样的问题。我的猜测是,由于JS对象上的键最终需要是字符串,它只是运行
value.toString()
而不是首选的
值。tojsonandrunstomserializer().toString()
public class GsonConfigurer {

private Map<Class<?>, Object> typeAdapterMap;

public Gson create() {
    final GsonBuilder gsonBuilder = new GsonBuilder();

    for (final Entry<Class<?>, Object> typeAdapterMapping : typeAdapterMap.entrySet()) {
        gsonBuilder.registerTypeAdapter(typeAdapterMapping.getKey(), typeAdapterMapping.getValue());
    }

    return gsonBuilder.create();
}

protected Map<Class<?>, Object> getTypeAdapterMap() {
    return typeAdapterMap;
}

public void setTypeAdapterMap(final Map<Class<?>, Object> typeAdapterMap) {
    this.typeAdapterMap = typeAdapterMap;
}

}
<bean id="gsonConfigurer" class="com.sfweb.gson.GsonConfigurer">
    <property name="typeAdapterMap">
        <util:map key-type="java.lang.Class">
            <entry key="com.sfweb.dto.CheckoutConfigurationOption">
                <bean class="com.sfweb.dto.deserializer.CheckoutConfigurationOptionGsonDeserializer" />
            </entry>
            <entry key="com.sfweb.dto.CheckoutClientConfigurationOption">
                <bean class="com.sfweb.dto.serializer.CheckoutClientConfigurationOptionGsonSerializer" />
            </entry>
        </util:map>
    </property>
</bean>

<bean class="com.google.gson.Gson" factory-bean="gsonConfigurer" factory-method="create" />
public class LowercaseEnumTypeAdapterFactory implements TypeAdapter.Factory {
  public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
    Class<T> rawType = (Class<T>) type.getRawType();
    if (!rawType.isEnum()) {
      return null;
    }

    final Map<String, T> lowercaseToConstant = new HashMap<String, T>();
    for (T constant : rawType.getEnumConstants()) {
      lowercaseToConstant.put(toLowercase(constant), constant);
    }

    return new TypeAdapter<T>() {
      public void write(JsonWriter out, T value) throws IOException {
        if (value == null) {
          out.nullValue();
        } else {
          out.value(toLowercase(value));
        }
      }

      public T read(JsonReader reader) throws IOException {
        if (reader.peek() == JsonToken.NULL) {
          reader.nextNull();
          return null;
        } else {
          return lowercaseToConstant.get(reader.nextString());
        }
      }
    };
  }

  private String toLowercase(Object o) {
    return o.toString().toLowerCase(Locale.US);
  }
}