{@code}public class LowercaseEnumTypeAdapterFactory implements TypeAdapterFactory publicTypeAdapter create(Gson gson, TypeToken type) { Class rawType = (Class ) type.getRawType(); if (!rawType.isEnum()) { return null; } final Map lowercaseToConstant = new HashMap (); for (T constant : rawType.getEnumConstants()) { lowercaseToConstant.put(toLowercase(constant), constant); } return new TypeAdapter () { 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); } } }
Type adapter factories select which types they provide type adapters for. If a factory cannot support a given type, it must return null when that type is passed to {@link #create}. Factories should expect {@code create()} to be called on them for many types and should return null formost of those types. In the above example the factory returns null for calls to {@code create()} where {@code type} is not an enum.
A factory is typically called once per type, but the returned type adapter may be used many times. It is most efficient to do expensive work like reflection in {@code create()} so that the type adapter's {@code read()} and {@code write()} methods can be very fast. In this example themapping from lowercase name to enum value is computed eagerly.
As with type adapters, factories must be registered with a {@link com.google.gson.GsonBuilder} for them to take effect:
{@code GsonBuilder builder = new GsonBuilder(); builder.registerTypeAdapterFactory(new LowercaseEnumTypeAdapterFactory()); ... Gson gson = builder.create();}If multiple factories support the same type, the factory registered earlier takes precedence.
The type adapter delegates to another type adapter for the multiset elements. It figures out the element type by reflecting on the multiset's type token. A {@code Gson} is passed in to {@code create} forjust this purpose:
{@code}public class MultisetTypeAdapterFactory implements TypeAdapterFactory publicDelegating from one type adapter to another is extremely powerful; it's the foundation of how Gson converts Java objects and collections. Whenever possible your factory should retrieve its delegate type adapter in the {@code create()} method; this ensures potentially-expensive type adaptercreation happens only once. @since 2.1TypeAdapter create(Gson gson, TypeToken typeToken) { Type type = typeToken.getType(); if (typeToken.getRawType() != Multiset.class || !(type instanceof ParameterizedType)) { return null; } Type elementType = ((ParameterizedType) type).getActualTypeArguments()[0]; TypeAdapter> elementAdapter = gson.getAdapter(TypeToken.get(elementType)); return (TypeAdapter ) newMultisetAdapter(elementAdapter); } private TypeAdapter > newMultisetAdapter( final TypeAdapter elementAdapter) { return new TypeAdapter >() { public void write(JsonWriter out, Multiset value) throws IOException { if (value == null) { out.nullValue(); return; } out.beginArray(); for (Multiset.Entry entry : value.entrySet()) { out.value(entry.getCount()); elementAdapter.write(out, entry.getElement()); } out.endArray(); } public Multiset read(JsonReader in) throws IOException { if (in.peek() == JsonToken.NULL) { in.nextNull(); return null; } Multiset result = LinkedHashMultiset.create(); in.beginArray(); while (in.hasNext()) { int count = in.nextInt(); E element = elementAdapter.read(in); result.add(element, count); } in.endArray(); return result; } }; } } }
{@code}public class LowercaseEnumTypeAdapterFactory implements TypeAdapter.Factory publicTypeAdapter create(Gson gson, TypeToken type) { Class rawType = (Class ) type.getRawType(); if (!rawType.isEnum()) { return null; } final Map lowercaseToConstant = new HashMap (); for (T constant : rawType.getEnumConstants()) { lowercaseToConstant.put(toLowercase(constant), constant); } return new TypeAdapter () { 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); } } }
Type adapter factories select which types they provide type adapters for. If a factory cannot support a given type, it must return null when that type is passed to {@link #create}. Factories should expect {@code create()} to be called on them for many types and should return null formost of those types. In the above example the factory returns null for calls to {@code create()} where {@code type} is not an enum.
A factory is typically called once per type, but the returned type adapter may be used many times. It is most efficient to do expensive work like reflection in {@code create()} so that the type adapter's {@code read()} and {@code write()} methods can be very fast. In this example themapping from lowercase name to enum value is computed eagerly.
As with type adapters, factories must be registered with a {@link com.massivecraft.mcore.xlib.gson.GsonBuilder} for them to take effect:
{@code GsonBuilder builder = new GsonBuilder(); builder.registerTypeAdapterFactory(new LowercaseEnumTypeAdapterFactory()); ... Gson gson = builder.create();}If multiple factories support the same type, the factory registered earlier takes precedence.
The type adapter delegates to another type adapter for the multiset elements. It figures out the element type by reflecting on the multiset's type token. A {@code Gson} is passed in to {@code create} forjust this purpose:
{@code}public class MultisetTypeAdapterFactory implements TypeAdapter.Factory publicDelegating from one type adapter to another is extremely powerful; it's the foundation of how Gson converts Java objects and collections. Whenever possible your factory should retrieve its delegate type adapter in the {@code create()} method; this ensures potentially-expensive type adaptercreation happens only once. @since 2.1TypeAdapter create(Gson gson, TypeToken typeToken) { Type type = typeToken.getType(); if (typeToken.getRawType() != Multiset.class || !(type instanceof ParameterizedType)) { return null; } Type elementType = ((ParameterizedType) type).getActualTypeArguments()[0]; TypeAdapter> elementAdapter = gson.getAdapter(TypeToken.get(elementType)); return (TypeAdapter ) newMultisetAdapter(elementAdapter); } private TypeAdapter > newMultisetAdapter( final TypeAdapter elementAdapter) { return new TypeAdapter >() { public void write(JsonWriter out, Multiset value) throws IOException { if (value == null) { out.nullValue(); return; } out.beginArray(); for (Multiset.Entry entry : value.entrySet()) { out.value(entry.getCount()); elementAdapter.write(out, entry.getElement()); } out.endArray(); } public Multiset read(JsonReader in) throws IOException { if (in.peek() == JsonToken.NULL) { in.nextNull(); return null; } Multiset result = LinkedHashMultiset.create(); in.beginArray(); while (in.hasNext()) { int count = in.nextInt(); E element = elementAdapter.read(in); result.add(element, count); } in.endArray(); return result; } }; } } }
|
|
|
|
|
|
|
|
|
|
|
|