public void run() throws Exception { Moshi moshi = new Moshi.Builder() .add(new SortedSetAdapterFactory()) .build(); JsonAdapter<SortedSet<String>> jsonAdapter = moshi.adapter( Types.newParameterizedType(SortedSet.class, String.class)); TreeSet<String> model = new TreeSet<>(); model.add("a"); model.add("b"); model.add("c"); String json = jsonAdapter.toJson(model); System.out.println(json); }
static Type getGenericSuperclass(Type type) { Class<?> rawType = Types.getRawType(type); return resolve(type, rawType, rawType.getGenericSuperclass()); }
@Override public @Nullable JsonAdapter<?> create(Type type, Set<? extends Annotation> annotations, Moshi moshi) { if ((type == Long.class || type == long.class) && Types.nextAnnotations(annotations, Uint64.class) != null) { return UINT64_JSON_ADAPTER; } Class<?> rawType = Types.getRawType(type); if (rawType == List.class && ((ParameterizedType) type).getActualTypeArguments()[0] == Long.class && Types.nextAnnotations(annotations, Uint64.class) != null) { return LIST_OF_UINT64_JSON_ADAPTER; } if (!annotations.isEmpty()) { return null; } if (rawType.equals(ByteString.class)) { return BYTE_STRING_JSON_ADAPTER; } if (Message.class.isAssignableFrom(rawType)) { return new MessageJsonAdapter(moshi, type); } return null; } }
@Override public @Nullable JsonAdapter<?> create( Type type, Set<? extends Annotation> annotations, Moshi moshi) { if (!annotations.isEmpty()) return null; Class<?> rawType = Types.getRawType(type); if (rawType != Map.class) return null; Type[] keyAndValue = Types.mapKeyAndValueTypes(type, rawType); return new MapJsonAdapter<>(moshi, keyAndValue[0], keyAndValue[1]).nullSafe(); } };
@Override public @Nullable JsonAdapter<?> create( Type type, Set<? extends Annotation> annotations, Moshi moshi) { Set<? extends Annotation> delegateAnnotations = Types.nextAnnotations(annotations, Enveloped.class); if (delegateAnnotations == null) { return null; } Type envelope = Types.newParameterizedTypeWithOwner(EnvelopeJsonAdapter.class, Envelope.class, type); JsonAdapter<Envelope<?>> delegate = moshi.nextAdapter(this, envelope, delegateAnnotations); return new EnvelopeJsonAdapter(delegate); } };
@Override public @Nullable JsonAdapter<?> create( Type type, Set<? extends Annotation> annotations, Moshi moshi) { Type elementType = Types.arrayComponentType(type); if (elementType == null) return null; if (!annotations.isEmpty()) return null; Class<?> elementClass = Types.getRawType(elementType); JsonAdapter<Object> elementAdapter = moshi.adapter(elementType); return new ArrayJsonAdapter(elementClass, elementAdapter).nullSafe(); } };
boolean elementTypeIsString(Type type) { Type elementType = Types.collectionElementType(type, Collection.class); Class<?> rawElementType = Types.getRawType(elementType); return rawElementType == String.class; } };
@Override public boolean equals(Object other) { return other instanceof WildcardType && Types.equals(this, (WildcardType) other); }
return null; Class<?> rawType = Types.getRawType(type); if (rawType.isInterface() || rawType.isEnum()) return null; if (!annotations.isEmpty()) return null; for (Type t = type; t != Object.class; t = Types.getGenericSuperclass(t)) { createFieldBindings(moshi, t, fields);
return null; Class<?> rawType = Types.getRawType(type); if (rawType.isInterface() || rawType.isEnum()) return null; if (Util.isPlatformType(rawType) && !Types.isAllowedPlatformType(rawType)) { throw new IllegalArgumentException("Platform " + typeAnnotatedWithAnnotations(type, annotations) for (Type t = type; t != Object.class; t = Types.getGenericSuperclass(t)) { createFieldBindings(moshi, t, fields);
@Override public JsonAdapter<?> create(Type type, Set<? extends Annotation> annotations, Moshi moshi) { Set<? extends Annotation> nextAnnotations = Types.nextAnnotations(annotations, FirstElement.class); if (nextAnnotations == null || !nextAnnotations.isEmpty()) return null; return new ElementAtJsonAdapter<>(type, moshi, 0); } };
static <T> JsonAdapter<Set<T>> newLinkedHashSetAdapter(Type type, Moshi moshi) { Type elementType = Types.collectionElementType(type, Collection.class); JsonAdapter<T> elementAdapter = moshi.adapter(elementType); return new CollectionJsonAdapter<Set<T>, T>(elementAdapter) { @Override Set<T> newCollection() { return new LinkedHashSet<>(); } }; }
@Override public JsonAdapter<?> create(Type type, Set<? extends Annotation> annotations, Moshi moshi) { if (annotations.isEmpty() || annotations.size() != 1 // At this point we know that the set contains only one entry. || annotations.iterator().next().annotationType() != ContactPath.class) { return null; } // Check that the host type is a list. Class<?> rawType = Types.getRawType(type); if (rawType != List.class) return null; // Check that the generic parameter is a list. Type paramType = Types.collectionElementType(type, List.class); Class<?> rawParamType = Types.getRawType(paramType); if (rawParamType != List.class) return null; // Check that the generic parameter of paramType is XingUser. Type innerType = Types.collectionElementType(paramType, List.class); Class<?> rawInnerType = Types.getRawType(innerType); if (rawInnerType != XingUser.class) return null; // Create the adapter. At this point we know that paramType is the pathType. return new ContactPathJsonAdapter(moshi, paramType).nullSafe(); } };
@Override public @Nullable JsonAdapter<?> create( Type type, Set<? extends Annotation> annotations, Moshi moshi) { if (!annotations.isEmpty()) return null; Class<?> rawType = Types.getRawType(type); if (rawType != Map.class) return null; Type[] keyAndValue = Types.mapKeyAndValueTypes(type, rawType); return new MapJsonAdapter<>(moshi, keyAndValue[0], keyAndValue[1]).nullSafe(); } };
@Override public @Nullable JsonAdapter<?> create( Type type, Set<? extends Annotation> annotations, Moshi moshi) { Type elementType = Types.arrayComponentType(type); if (elementType == null) return null; if (!annotations.isEmpty()) return null; Class<?> elementClass = Types.getRawType(elementType); JsonAdapter<Object> elementAdapter = moshi.adapter(elementType); return new ArrayJsonAdapter(elementClass, elementAdapter).nullSafe(); } };
@Override public boolean equals(Object other) { return other instanceof ParameterizedType && Types.equals(this, (ParameterizedType) other); }
@Override public JsonAdapter<?> create(Type type, Set<? extends Annotation> annotations, Moshi moshi) { Set<? extends Annotation> nextAnnotations = Types.nextAnnotations(annotations, LastElement.class); if (nextAnnotations == null || !nextAnnotations.isEmpty()) return null; return new LastElementJsonAdapter<>(type, moshi); } };
static <T> JsonAdapter<Collection<T>> newArrayListAdapter(Type type, Moshi moshi) { Type elementType = Types.collectionElementType(type, Collection.class); JsonAdapter<T> elementAdapter = moshi.adapter(elementType); return new CollectionJsonAdapter<Collection<T>, T>(elementAdapter) { @Override Collection<T> newCollection() { return new ArrayList<>(); } }; }
public static Class<?> getRawType(Type type) { if (type instanceof Class<?>) { // type is a normal class. return (Class<?>) type; } else if (type instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType) type; // I'm not exactly sure why getRawType() returns Type instead of Class. Neal isn't either but // suspects some pathological case related to nested classes exists. Type rawType = parameterizedType.getRawType(); return (Class<?>) rawType; } else if (type instanceof GenericArrayType) { Type componentType = ((GenericArrayType) type).getGenericComponentType(); return Array.newInstance(getRawType(componentType), 0).getClass(); } else if (type instanceof TypeVariable) { // We could use the variable's bounds, but that won't work if there are multiple. having a raw // type that's more general than necessary is okay. return Object.class; } else if (type instanceof WildcardType) { return getRawType(((WildcardType) type).getUpperBounds()[0]); } else { String className = type == null ? "null" : type.getClass().getName(); throw new IllegalArgumentException("Expected a Class, ParameterizedType, or " + "GenericArrayType, but <" + type + "> is of type " + className); } }
public void run() throws Exception { String json = "[\"DIAMONDS\", \"STARS\", \"HEARTS\"]"; Moshi moshi = new Moshi.Builder() .add(DefaultOnDataMismatchAdapter.newFactory(Suit.class, Suit.CLUBS)) .build(); JsonAdapter<List<Suit>> jsonAdapter = moshi.adapter( Types.newParameterizedType(List.class, Suit.class)); List<Suit> suits = jsonAdapter.fromJson(json); System.out.println(suits); }