com.squareup.moshi.adapters.RuntimeJsonAdapterFactory Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of moshi-adapters Show documentation
Show all versions of moshi-adapters Show documentation
A modern JSON API for Android and Java
/*
* Copyright (C) 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.squareup.moshi.adapters;
import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.JsonDataException;
import com.squareup.moshi.JsonReader;
import com.squareup.moshi.JsonWriter;
import com.squareup.moshi.Moshi;
import com.squareup.moshi.Types;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import javax.annotation.CheckReturnValue;
/**
* A JsonAdapter factory for polymorphic types. This is useful when the type is not known before
* decoding the JSON. This factory's adapters expect JSON in the format of a JSON object with a
* key whose value is a label that determines the type to which to map the JSON object.
*/
// TODO(jwilson): make this class public in Moshi 1.8.
final class RuntimeJsonAdapterFactory implements JsonAdapter.Factory {
final Class baseType;
final String labelKey;
final Map labelToType = new LinkedHashMap<>();
/**
* @param baseType The base type for which this factory will create adapters. Cannot be Object.
* @param labelKey The key in the JSON object whose value determines the type to which to map the
* JSON object.
*/
@CheckReturnValue
public static RuntimeJsonAdapterFactory of(Class baseType, String labelKey) {
if (baseType == null) throw new NullPointerException("baseType == null");
if (labelKey == null) throw new NullPointerException("labelKey == null");
if (baseType == Object.class) {
throw new IllegalArgumentException(
"The base type must not be Object. Consider using a marker interface.");
}
return new RuntimeJsonAdapterFactory<>(baseType, labelKey);
}
RuntimeJsonAdapterFactory(Class baseType, String labelKey) {
this.baseType = baseType;
this.labelKey = labelKey;
}
/**
* Register the subtype that can be created based on the label. When an unknown type is found
* during encoding an {@linkplain IllegalArgumentException} will be thrown. When an unknown label
* is found during decoding a {@linkplain JsonDataException} will be thrown.
*/
public RuntimeJsonAdapterFactory registerSubtype(Class extends T> subtype, String label) {
if (subtype == null) throw new NullPointerException("subtype == null");
if (label == null) throw new NullPointerException("label == null");
if (labelToType.containsKey(label) || labelToType.containsValue(subtype)) {
throw new IllegalArgumentException("Subtypes and labels must be unique.");
}
labelToType.put(label, subtype);
return this;
}
@Override
public JsonAdapter> create(Type type, Set extends Annotation> annotations, Moshi moshi) {
if (Types.getRawType(type) != baseType || !annotations.isEmpty()) {
return null;
}
int size = labelToType.size();
Map> labelToAdapter = new LinkedHashMap<>(size);
Map typeToLabel = new LinkedHashMap<>(size);
for (Map.Entry entry : labelToType.entrySet()) {
String label = entry.getKey();
Type typeValue = entry.getValue();
typeToLabel.put(typeValue, label);
labelToAdapter.put(label, moshi.adapter(typeValue));
}
JsonAdapter
© 2015 - 2024 Weber Informatics LLC | Privacy Policy