下面列出了com.fasterxml.jackson.databind.JavaType#isContainerType ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
public static boolean isBean(Type type) {
if (type == null) {
return false;
}
JavaType javaType = TypeFactory.defaultInstance().constructType(type);
if (javaType.isContainerType() || javaType.isEnumType()) {
return false;
}
Class<?> cls = javaType.getRawClass();
if (ClassUtils.isPrimitiveOrWrapper(cls)) {
return false;
}
return (cls != String.class
&& cls != Date.class
&& cls != LocalDate.class
&& cls != byte[].class
&& cls != File.class
&& !cls.getName().equals("org.springframework.web.multipart.MultipartFile")
&& !Part.class.isAssignableFrom(cls));
}
/**
* Helper method used to decide whether we can omit introspection
* for members (methods, fields, constructors); we may do so for
* a limited number of container types JDK provides.
*/
protected boolean _isStdJDKCollection(JavaType type)
{
if (!type.isContainerType() || type.isArrayType()) {
return false;
}
Class<?> raw = type.getRawClass();
String pkgName = ClassUtil.getPackageName(raw);
if (pkgName != null) {
if (pkgName.startsWith("java.lang")
|| pkgName.startsWith("java.util")) {
/* 23-Sep-2014, tatu: Should we be conservative here (minimal number
* of matches), or ambitious? Let's do latter for now.
*/
if (Collection.class.isAssignableFrom(raw)
|| Map.class.isAssignableFrom(raw)) {
return true;
}
}
}
return false;
}
@Override
public JavaType modifyType(JavaType type, Type jdkType, TypeBindings bindings, TypeFactory typeFactory)
{
if (type.isReferenceType() || type.isContainerType()) {
return type;
}
final Class<?> raw = type.getRawClass();
// First: make Multimaps look more Map-like
if (raw == Multimap.class) {
return MapLikeType.upgradeFrom(type,
type.containedTypeOrUnknown(0),
type.containedTypeOrUnknown(1));
}
if (raw == Optional.class) {
return ReferenceType.upgradeFrom(type, type.containedTypeOrUnknown(0));
}
return type;
}
@Override
public boolean useForType(JavaType type) {
Class<?> clazz = type.getRawClass();
// Note: This does not work well with generics defined at or above the same scope as the call
// to marshal or unmarshal. As a result, only use such generics there when dealing with a primitive
// type or registered class, as these will cope with the idResolver.
// We can lookup the class in the registry, for marshalling and unmarshalling.
Boolean registryHasClass = registry.isClass(clazz);
// We only ever declare as object if we intend to use one of our own classes (or a primitive).
Boolean isObject = (Object.class.equals(clazz));
// Also include abstract classes and interfaces as these are always defined with a type id. This
// is not the case for container types, however, so these are excluded.
Boolean isAbstract = type.isAbstract();
Boolean isInterface = type.isInterface();
Boolean isNotContainer = !type.isContainerType();
// Primitive types are considered abstract, so exclude these as well.
Boolean isNotPrimitive = !type.isPrimitive();
return registryHasClass || ((isObject || isAbstract || isInterface) && isNotContainer && isNotPrimitive);
}
@Override
public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException {
final Class<?> classToDeserialize;
if (property != null) {
final JavaType type = property.getType();
classToDeserialize = type.isContainerType() ? type.getContentType().getRawClass() : type.getRawClass();
} else {
classToDeserialize = ctxt.getContextualType().getRawClass();
}
return new ClassWithInterfaceFieldsDeserializer(classToDeserialize.getName());
}
private void checkType(JavaType type) {
// 原子类型/string在java中是abstract的
if (type.getRawClass().isPrimitive()
|| propertyCreatorMap.containsKey(type.getRawClass())
|| String.class.equals(type.getRawClass())
|| concreteInterfaces.contains(type.getRawClass())) {
return;
}
String msg = "Must be a concrete type.";
if (type.isMapLikeType()) {
Class<?> keyTypeClass = type.getKeyType().getRawClass();
if (!String.class.equals(keyTypeClass)) {
// swagger中map的key只允许为string
throw new Error("Type of key in map must be string, but got " + keyTypeClass.getName());
}
}
if (type.isContainerType()) {
checkType(type.getContentType());
return;
}
if (type.getRawClass().isInterface()) {
throw new ServiceCombException(type.getTypeName() + " is interface. " + msg);
}
if (Modifier.isAbstract(type.getRawClass().getModifiers())) {
throw new ServiceCombException(type.getTypeName() + " is abstract class. " + msg);
}
}
private HeaderProcessor createProcessor(String name, Type type, String defaultValue, boolean required) {
JavaType javaType = TypeFactory.defaultInstance().constructType(type);
HeaderParameter headerParameter = new HeaderParameter();
headerParameter.name(name)
.required(required)
.setDefaultValue(defaultValue);
if (javaType.isContainerType()) {
headerParameter.type(ArrayProperty.TYPE);
}
return new HeaderProcessor(headerParameter, javaType);
}
private ParamValueProcessor createProcessor(String name, Class<?> type, String defaultValue, boolean required,
String collectionFormat) {
JavaType javaType = TypeFactory.defaultInstance().constructType(type);
QueryParameter queryParameter = new QueryParameter();
queryParameter.name(name)
.required(required)
.collectionFormat(collectionFormat)
.setDefaultValue(defaultValue);
if (javaType.isContainerType()) {
queryParameter.type(ArrayProperty.TYPE);
}
return new QueryProcessor(queryParameter, javaType);
}
private FormProcessor createProcessor(String name, Type type, String defaultValue, boolean required) {
JavaType javaType = TypeFactory.defaultInstance().constructType(type);
FormParameter formParameter = new FormParameter();
formParameter.name(name)
.required(required)
.setDefaultValue(defaultValue);
if (javaType.isContainerType()) {
formParameter.type(ArrayProperty.TYPE);
}
return new FormProcessor(formParameter, javaType);
}
/**
* Accessor used to find out "default value" to use for comparing values to
* serialize, to determine whether to exclude value from serialization with
* inclusion type of {@link com.fasterxml.jackson.annotation.JsonInclude.Include#NON_DEFAULT}.
*<p>
* Default logic is such that for primitives and wrapper types for primitives, expected
* defaults (0 for `int` and `java.lang.Integer`) are returned; for Strings, empty String,
* and for structured (Maps, Collections, arrays) and reference types, criteria
* {@link com.fasterxml.jackson.annotation.JsonInclude.Include#NON_DEFAULT}
* is used.
*
* @since 2.7
*/
public static Object getDefaultValue(JavaType type)
{
// 06-Nov-2015, tatu: Returning null is fine for Object types; but need special
// handling for primitives since they are never passed as nulls.
Class<?> cls = type.getRawClass();
// 30-Sep-2016, tatu: Also works for Wrappers, so both `Integer.TYPE` and `Integer.class`
// would return `Integer.TYPE`
Class<?> prim = ClassUtil.primitiveType(cls);
if (prim != null) {
return ClassUtil.defaultValue(prim);
}
if (type.isContainerType() || type.isReferenceType()) {
return JsonInclude.Include.NON_EMPTY;
}
if (cls == String.class) {
return "";
}
// 09-Mar-2016, tatu: Not sure how far this path we want to go but for now
// let's add `java.util.Date` and `java.util.Calendar`, as per [databind#1550]
if (type.isTypeOrSubTypeOf(Date.class)) {
return new Date(0L);
}
if (type.isTypeOrSubTypeOf(Calendar.class)) {
Calendar c = new GregorianCalendar();
c.setTimeInMillis(0L);
return c;
}
return null;
}
protected boolean _suitableType(JavaType type)
{
// Future plans may include calling of this method for all kinds of abstract types.
// So as simple precaution, let's limit kinds of types we will try materialize
// implementations for.
if (type.isContainerType() || type.isReferenceType()
|| type.isEnumType() || type.isPrimitive()) {
return false;
}
Class<?> cls = type.getRawClass();
if ((cls == Number.class)
// 22-Jun-2016, tatu: As per [#12], avoid these too
|| (cls == Date.class) || (cls == Calendar.class)
|| (cls == CharSequence.class) || (cls == Iterable.class) || (cls == Iterator.class)
// 06-Feb-2019, tatu: [modules-base#74] and:
|| (cls == java.io.Serializable.class)
) {
return false;
}
// Fail on non-public classes, since we can't easily force access to such
// classes (unless we tried to generate impl classes in same package)
if (!Modifier.isPublic(cls.getModifiers())) {
if (isEnabled(Feature.FAIL_ON_NON_PUBLIC_TYPES)) {
throw new IllegalArgumentException("Can not materialize implementation of "+cls+" since it is not public ");
}
return false;
}
return true;
}
private static Schema<?> createSchema(ParamPOJO paramPOJO, Path modelsDir) {
final Schema<?> schema;
if (paramPOJO.getDatatype() == null) {
JavaType javaType = ApiHelper.constructJavaType(paramPOJO);
if (javaType.isContainerType()) {
return generateSchema(javaType, modelsDir);
} else {
return createSchemaPOJO(paramPOJO);
}
}
switch (paramPOJO.getDatatype()) {
case STRING:
schema = new StringSchema();
break;
case BOOLEAN:
schema = new BooleanSchema();
break;
case INTEGER:
schema = new IntegerSchema();
break;
case LONG:
schema = new IntegerSchema();
schema.format("int64");
break;
case NUMBER:
schema = new NumberSchema();
break;
case ENUM:
schema = createSchemaPOJO(paramPOJO);
break;
default:
throw new UnsupportedOperationException();
}
return schema;
}
@Override
public JavaType modifyType(JavaType type, Type jdkType, TypeBindings bindings, TypeFactory typeFactory) {
if (type.isReferenceType() || type.isContainerType()) {
return type;
}
final Class<?> raw = type.getRawClass();
if (raw == Option.class)
return ReferenceType.upgradeFrom(type, type.containedTypeOrUnknown(0));
if (raw == Eval.class)
return ReferenceType.upgradeFrom(type, type.containedTypeOrUnknown(0));
if (raw == Trampoline.class)
return ReferenceType.upgradeFrom(type, type.containedTypeOrUnknown(0));
if (raw == Either.class)
return ReferenceType.upgradeFrom(type, type.containedTypeOrUnknown(0));
if (raw == Value.class)
return ReferenceType.upgradeFrom(type, type.containedTypeOrUnknown(0));
for(Class c : collectionLikeTypes){
if (c.isAssignableFrom(raw)) {
// return CollectionType.upgradeFrom(type, type.containedTypeOrUnknown(0));
return CollectionLikeType.upgradeFrom(type, type.containedTypeOrUnknown(0));
}
}
return type;
}
protected void validateType(JavaType type, DeserializationTypeValidator validator, List<String> invalidTypes) {
if (!type.isPrimitive()) {
if (!type.isArrayType()) {
validateTypeInternal(type, validator, invalidTypes);
}
if (type.isMapLikeType()) {
validateType(type.getKeyType(), validator, invalidTypes);
}
if (type.isContainerType() || type.hasContentType()) {
validateType(type.getContentType(), validator, invalidTypes);
}
}
}
protected void validateType(JavaType type, DeserializationTypeValidator validator, List<String> invalidTypes) {
if (!type.isPrimitive()) {
if (!type.isArrayType()) {
validateTypeInternal(type, validator, invalidTypes);
}
if (type.isMapLikeType()) {
validateType(type.getKeyType(), validator, invalidTypes);
}
if (type.isContainerType() || type.hasContentType()) {
validateType(type.getContentType(), validator, invalidTypes);
}
}
}
@Override
protected void writeInternal(Object object, Type type, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException {
MediaType contentType = outputMessage.getHeaders().getContentType();
JsonEncoding encoding = getJsonEncoding(contentType);
JsonGenerator generator = this.objectMapper.getFactory().createGenerator(outputMessage.getBody(), encoding);
try {
writePrefix(generator, object);
Class<?> serializationView = null;
FilterProvider filters = null;
Object value = object;
JavaType javaType = null;
if (object instanceof MappingJacksonValue) {
MappingJacksonValue container = (MappingJacksonValue) object;
value = container.getValue();
serializationView = container.getSerializationView();
filters = container.getFilters();
}
if (type != null && value != null && TypeUtils.isAssignable(type, value.getClass())) {
javaType = getJavaType(type, null);
}
ObjectWriter objectWriter;
if (serializationView != null) {
objectWriter = this.objectMapper.writerWithView(serializationView);
}
else if (filters != null) {
objectWriter = this.objectMapper.writer(filters);
}
else {
objectWriter = this.objectMapper.writer();
}
if (javaType != null && javaType.isContainerType()) {
objectWriter = objectWriter.forType(javaType);
}
SerializationConfig config = objectWriter.getConfig();
if (contentType != null && contentType.isCompatibleWith(TEXT_EVENT_STREAM) &&
config.isEnabled(SerializationFeature.INDENT_OUTPUT)) {
objectWriter = objectWriter.with(this.ssePrettyPrinter);
}
objectWriter.writeValue(generator, value);
writeSuffix(generator, object);
generator.flush();
}
catch (JsonProcessingException ex) {
throw new HttpMessageNotWritableException("Could not write JSON: " + ex.getOriginalMessage(), ex);
}
}
/**
* Factory method for creating a subtype of given base type, as defined
* by specified subclass; but retaining generic type information if any.
* Can be used, for example, to get equivalent of "HashMap<String,Integer>"
* from "Map<String,Integer>" by giving <code>HashMap.class</code>
* as subclass.
*/
public JavaType constructSpecializedType(JavaType baseType, Class<?> subclass)
{
// simple optimization to avoid costly introspection if type-erased type does NOT differ
final Class<?> rawBase = baseType.getRawClass();
if (rawBase == subclass) {
return baseType;
}
JavaType newType;
// also: if we start from untyped, not much to save
do { // bogus loop to be able to break
if (rawBase == Object.class) {
newType = _fromClass(null, subclass, EMPTY_BINDINGS);
break;
}
if (!rawBase.isAssignableFrom(subclass)) {
throw new IllegalArgumentException(String.format(
"Class %s not subtype of %s", subclass.getName(), baseType));
}
// A few special cases where we can simplify handling:
// (1) Original target type has no generics -- just resolve subtype
if (baseType.getBindings().isEmpty()) {
newType = _fromClass(null, subclass, EMPTY_BINDINGS);
break;
}
// (2) A small set of "well-known" List/Map subtypes where can take a short-cut
if (baseType.isContainerType()) {
if (baseType.isMapLikeType()) {
if ((subclass == HashMap.class)
|| (subclass == LinkedHashMap.class)
|| (subclass == EnumMap.class)
|| (subclass == TreeMap.class)) {
newType = _fromClass(null, subclass,
TypeBindings.create(subclass, baseType.getKeyType(), baseType.getContentType()));
break;
}
} else if (baseType.isCollectionLikeType()) {
if ((subclass == ArrayList.class)
|| (subclass == LinkedList.class)
|| (subclass == HashSet.class)
|| (subclass == TreeSet.class)) {
newType = _fromClass(null, subclass,
TypeBindings.create(subclass, baseType.getContentType()));
break;
}
// 29-Oct-2015, tatu: One further shortcut: there are variants of `EnumSet`,
// but they are impl details and we basically do not care...
if (rawBase == EnumSet.class) {
return baseType;
}
}
}
// (3) Sub-class does not take type parameters -- just resolve subtype
int typeParamCount = subclass.getTypeParameters().length;
if (typeParamCount == 0) {
newType = _fromClass(null, subclass, EMPTY_BINDINGS);
break;
}
// (4) If all else fails, do the full traversal using placeholders
TypeBindings tb = _bindingsForSubtype(baseType, typeParamCount, subclass);
newType = _fromClass(null, subclass, tb);
} while (false);
// 25-Sep-2016, tatu: As per [databind#1384] also need to ensure handlers get
// copied as well
newType = newType.withHandlersFrom(baseType);
return newType;
}
@Override
@SuppressWarnings("deprecation")
protected void writeInternal(Object object, Type type, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException {
JsonEncoding encoding = getJsonEncoding(outputMessage.getHeaders().getContentType());
JsonGenerator generator = this.objectMapper.getFactory().createGenerator(outputMessage.getBody(), encoding);
try {
writePrefix(generator, object);
Class<?> serializationView = null;
FilterProvider filters = null;
Object value = object;
JavaType javaType = null;
if (object instanceof MappingJacksonValue) {
MappingJacksonValue container = (MappingJacksonValue) object;
value = container.getValue();
serializationView = container.getSerializationView();
filters = container.getFilters();
}
if (jackson26Available && type != null && value != null && TypeUtils.isAssignable(type, value.getClass())) {
javaType = getJavaType(type, null);
}
ObjectWriter objectWriter;
if (serializationView != null) {
objectWriter = this.objectMapper.writerWithView(serializationView);
}
else if (filters != null) {
objectWriter = this.objectMapper.writer(filters);
}
else {
objectWriter = this.objectMapper.writer();
}
if (javaType != null && javaType.isContainerType()) {
objectWriter = objectWriter.withType(javaType);
}
objectWriter.writeValue(generator, value);
writeSuffix(generator, object);
generator.flush();
}
catch (JsonProcessingException ex) {
throw new HttpMessageNotWritableException("Could not write content: " + ex.getMessage(), ex);
}
}