2012-03-23 17 views
3

シリアル化しているオブジェクトには、列挙型のキーを持つマップが含まれています。これらの列挙型には変数があります。私はGSONでシリアル化するとき、結果のJSONにデフォルトのEnum名の代わりにEnum変数を持たせたいと思います。カスタムシリアライザを作成して登録しようとしましたが、そのトリックは行っていません。ここに私のコードです。GSONカスタム・シリアライザ(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)); 
} 
} 

CheckoutClientConfigurationDto(マイナスすべての定型ゲッター/セッター):

public class CheckoutClientConfigurationDto implements Dto { 

private String wlcHost; 

private String clientId; 

private String appId; 

private String id; 

private Map<CheckoutClientConfigurationOption, Boolean> options; 

public CheckoutClientConfigurationDto() { 
    products = new ArrayList<ProductDto>(); 
    options = new HashMap<CheckoutClientConfigurationOption, Boolean>(); 
} 

public Map<CheckoutClientConfigurationOption, Boolean> getOptions() { 
    return options; 
} 

public void setOptions(final Map<CheckoutClientConfigurationOption, Boolean> options) { 
    this.options = options; 
} 
} 

CheckoutClientConfigurationOption:

public enum CheckoutClientConfigurationOption { 

SHOW_SAVED_ADDRESSES("showSavedAddresses", true), 
SHOW_CART_SUMMARY("showCartSummary", true), 
REMOVE_CART_ITEMS("removeCartItems", true), 
SHOW_DISCOUNT_FIELD("showDiscountField", true), 
SHOW_VAT_CODE("showVatCode", true), 
SHOW_ORDER_CONFIRMATION("showOrderConfirmation", true), 
SHOW_CANCEL_BUTTON("showCancelButton", false), 
SINGLE_PAGE_CHECKOUT("singlePageCheckout", false), 
SEND_ORDER_CONFIRMATION_EMAIL("sendOrderConfirmationEmail", true), 
SEND_SHIPPING_CONFIRMATION_EMAIL("sendShippingConfirmationEmail", true); 

private String optionName; 

private boolean defaultValue; 

private CheckoutClientConfigurationOption(final String optionName, final boolean defaultValue) { 
    this.optionName = optionName; 
    this.defaultValue = defaultValue; 
} 

public boolean getDefautValue() { 
    return defaultValue; 
} 

public String getOptionName() { 
    return optionName; 
} 
} 

マイカスタムGSON・シリアライザ:

public class CheckoutClientConfigurationOptionGsonSerializer implements JsonSerializer<CheckoutClientConfigurationOption> { 

@Override 
public JsonElement serialize(CheckoutClientConfigurationOption src, Type typeOfSrc, JsonSerializationContext context) { 
    return new 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; 
} 

} 

XML:

<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" /> 

あなたがXMLで見ることができるように私はまた、カスタムデシリアライザを持っています。それは問題なく動作します。デバッグモードで動作し、CheckoutClientConfigurationOptionGsonSerializerの行は決してヒットしません。私はJson()と呼ぶgsonオブジェクトがカスタムシリアライザを持っていることを確認しました。だから私は問題が何であるか分かりません。私はちょうど1枚が欠けていると感じています。

結果のJSONに「showSavedAddresses」と言ってもらいたいが、代わりに「SHOW_SAVED_ADDRESSES」と言っている。助けを前にありがとう!

+0

私は同じ問題を抱えています。私の推測では、JSオブジェクトのキーは最終的に文字列にする必要があるので、単に 'value.toJsonAndRunCustomSerializer()。toString()'の代わりに 'value.toString()'を実行するだけです。 – jpsimons

答えて

0

TypeAdapterFactory's documentationを十分に勉強することができます。列挙型を小文字にフォーマットする例が含まれています。これをあなたのニーズに合わせて変更することができます。

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); 
    } 
} 
+0

私はこのルートを試みましたが、私はかなり同じ結果を得ました。私は問題が私のenumが私のマップのキーとして埋め込まれているという事実を発見しています。私はそれを私のDTOの単一の変数として持っていれば問題なしで列挙型を小文字として直列化しますが、私はそれを私のカスタム・シリアライザまたはカスタム・タイプのアダプタと呼ぶことはありません。 –

2

GsonBuilder#enableComplexMapKeySerialization上のドキュメントを読む私はこれを参照してください。

マップのシリアライゼーションのデフォルトの実装は、だから、上のあなたのTypeAdapterを実行しませんキー

にtoString()を使用していますデフォルトではマップキーです。私はこのメソッドを呼び出すだけで、数値列として表示するように列挙しました。

関連する問題