下面列出了怎么用com.fasterxml.jackson.annotation.JsonPropertyOrder的API类实例代码及写法,或者点击链接到github查看源代码。
@Test
public void testCreateClass() throws Exception {
Class<?> c = DynamicClassFactory.INSTANCE.fetchOrCreatePairClass(new ClassPair(String.class, Date.class));
KVPair pair = (KVPair) c.newInstance();
assertEquals(1, c.getInterfaces().length);
assertEquals(KVPair.class, c.getInterfaces()[0]);
Annotation[] as = c.getAnnotations();
assertEquals(1, as.length);
assertEquals(JsonPropertyOrder.class, as[0].annotationType());
assertEquals(String.class, c.getMethod("getKey").getReturnType());
assertEquals(Date.class, c.getMethod("getValue").getReturnType());
assertEquals(String.class, c.getMethod("setKey", String.class).getParameterTypes()[0]);
assertEquals(Date.class, c.getMethod("setValue", Date.class).getParameterTypes()[0]);
Date date = new Date();
pair.key("key");
pair.value(date);
assertEquals("key", pair.key());
assertEquals(date, pair.value());
}
@SuppressWarnings({"unchecked", "rawtypes"})
public ResourceInformation build(Class<?> resourceClass) {
List<AnnotatedResourceField> resourceFields = getResourceFields(resourceClass);
String resourceType = getResourceType(resourceClass);
Optional<JsonPropertyOrder> propertyOrder = ClassUtils.getAnnotation(resourceClass, JsonPropertyOrder.class);
if (propertyOrder.isPresent()) {
JsonPropertyOrder propertyOrderAnnotation = propertyOrder.get();
Collections.sort(resourceFields, new FieldOrderedComparator(propertyOrderAnnotation.value(), propertyOrderAnnotation.alphabetic()));
}
DefaultResourceInstanceBuilder<?> instanceBuilder = new DefaultResourceInstanceBuilder(resourceClass);
Class<?> superclass = resourceClass.getSuperclass();
String superResourceType = superclass != Object.class && context.accept(superclass) ? context.getResourceType(superclass) : null;
return new ResourceInformation(context.getTypeParser(), resourceClass, resourceType, superResourceType, instanceBuilder, (List) resourceFields);
}
/**
* Lookup the list of specifically sorted property names in the given type based on its {@link JsonPropertyOrder} annotation.
*
* @param declaringType type for which to lookup the list of specifically sorted property names
* @return {@link JsonPropertyOrder#value()} or empty list
*/
private List<String> getAnnotatedPropertyOrder(Class<?> declaringType) {
return Optional.ofNullable(declaringType.getAnnotation(JsonPropertyOrder.class))
.map(JsonPropertyOrder::value)
.filter(valueArray -> valueArray.length != 0)
.map(Arrays::asList)
.orElseGet(Collections::emptyList);
}
protected List<ResourceField> getResourceFields(Class<?> resourceClass, ResourceFieldAccess resourceAccess, boolean embedded) {
BeanInformation beanDesc = BeanInformation.get(resourceClass);
List<String> attributeNames = beanDesc.getAttributeNames();
List<ResourceField> fields = new ArrayList<>();
Set<String> relationIdFields = new HashSet<>();
for (String attributeName : attributeNames) {
BeanAttributeInformation attributeDesc = beanDesc.getAttribute(attributeName);
if (!isIgnored(attributeDesc)) {
InformationBuilder informationBuilder = context.getInformationBuilder();
InformationBuilder.FieldInformationBuilder fieldBuilder = informationBuilder.createResourceField();
buildResourceField(beanDesc, embedded, attributeDesc, fieldBuilder);
fields.add(fieldBuilder.build());
} else if (attributeDesc.getAnnotation(JsonApiRelationId.class).isPresent()) {
relationIdFields.add(attributeDesc.getName());
}
}
if (!embedded) {
verifyRelationIdFields(resourceClass, relationIdFields, fields);
}
for (ResourceField resourceField : fields) {
ResourceFieldImpl impl = (ResourceFieldImpl) resourceField;
impl.setAccess(impl.getAccess().and(resourceAccess));
}
Optional<JsonPropertyOrder> propertyOrder = ClassUtils.getAnnotation(resourceClass, JsonPropertyOrder.class);
if (propertyOrder.isPresent()) {
JsonPropertyOrder propertyOrderAnnotation = propertyOrder.get();
Collections.sort(fields,
new FieldOrderedComparator(propertyOrderAnnotation.value(), propertyOrderAnnotation.alphabetic()));
}
return fields;
}
@Test
public void onGetAnnotationShouldReturnParentAnnotation() {
// WHEN
Optional<JsonPropertyOrder> result = ClassUtils.getAnnotation(ChildClass.class, JsonPropertyOrder.class);
// THEN
assertThat(result.get()).isInstanceOf(JsonPropertyOrder.class);
}
private Class<?> createClass(ClassPair classPair) {
String className = generateClassName(classPair);
String classStr = className.replaceAll("\\.", "/");
String keyClassType = Type.getDescriptor(classPair.keyClass);
String valueClassType = Type.getDescriptor(classPair.valueClass);
ClassWriter cw = new ClassWriter(0);
cw.visit(V1_7, ACC_PUBLIC + ACC_SUPER, className, null, "java/lang/Object", new String[]{interfaceName});
AnnotationVisitor anno = cw.visitAnnotation(Type.getDescriptor(JsonPropertyOrder.class), true);
AnnotationVisitor aa = anno.visitArray("value");
aa.visit("", "key");
aa.visit("", "value");
aa.visitEnd();
anno.visitEnd();
FieldVisitor keyField = cw.visitField(ACC_PRIVATE, "key", keyClassType, null, null);
keyField.visitEnd();
FieldVisitor valueField = cw.visitField(ACC_PRIVATE, "value", valueClassType, null, null);
valueField.visitEnd();
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitMaxs(2, 1);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, Type.getInternalName(Object.class), "<init>", "()V", false); // call the constructor of super class
mv.visitInsn(RETURN);
mv.visitEnd();
addGetterSetter(classPair, className, classStr, keyClassType, valueClassType, cw);
addKVPairMethods(classPair, className, classStr, keyClassType, valueClassType, cw);
cw.visitEnd();
return defineClass(className, cw.toByteArray());
}
@Test
public void onGetAnnotationShouldReturnParentAnnotation() {
// WHEN
Optional<JsonPropertyOrder> result = ClassUtils.getAnnotation(ChildClass.class, JsonPropertyOrder.class);
// THEN
assertThat(result.get()).isInstanceOf(JsonPropertyOrder.class);
}
private Collection<Property> unionOfSubclassProperties(Class<?> crdClass) {
TreeMap<String, Property> result = new TreeMap<>();
for (Class subtype : Property.subtypes(crdClass)) {
result.putAll(properties(subtype));
}
result.putAll(properties(crdClass));
JsonPropertyOrder order = crdClass.getAnnotation(JsonPropertyOrder.class);
return sortedProperties(order != null ? order.value() : null, result).values();
}
@Override
public void serializeContents(Object value, JsonGenerator jgen, SerializerProvider provider)
throws IOException
{
JsonPropertyOrder order = value.getClass().getAnnotation(JsonPropertyOrder.class);
String[] propOrder = (order == null) ? null : order.value();
if (propOrder == null) {
throw new IllegalStateException("Bean must declare JsonPropertyOrder!");
}
if (propOrder.length == 0) {
return;
}
int i = 0;
try {
do {
Field field = value.getClass().getDeclaredField(propOrder[i]);
ReflectionUtils.makeAccessible(field);
Object elem = field.get(value);
if (elem == null) {
provider.defaultSerializeNull(jgen);
}
else {
Class<?> cc = elem.getClass();
JsonSerializer<Object> serializer = provider.findValueSerializer(cc, null);
serializer.serialize(elem, jgen, provider);
}
++i;
}
while (i < propOrder.length);
}
catch (Exception e) {
// [JACKSON-55] Need to add reference information
wrapAndThrow(provider, e, value, i);
}
}
private List<String> annotationFields(Class<T> instanceClazz) {
if (instanceClazz.isAnnotationPresent(JsonPropertyOrder.class)) {
return Arrays.asList(instanceClazz.getAnnotation(JsonPropertyOrder.class).value());
}
throw new CatnapException("Missing CatnapOrder or JsonPropertyOrder annotation");
}
private boolean alphabetizeOrphans(Class<T> instanceClazz) {
if (instanceClazz.isAnnotationPresent(JsonPropertyOrder.class)) {
return instanceClazz.getAnnotation(JsonPropertyOrder.class).alphabetic();
}
throw new CatnapException("Missing CatnapOrder or JsonPropertyOrder annotation");
}
private <T> SortMethod sortMethod(Class<T> instanceClazz) {
if (instanceClazz != null) {
//Jackson Support
if (instanceClazz.isAnnotationPresent(JsonPropertyOrder.class)) {
String[] value = instanceClazz.getAnnotation(JsonPropertyOrder.class).value();
return (value != null && value.length > 0) ? SortMethod.ANNOTATION : SortMethod.ALPHABETICAL;
}
}
return SortMethod.FIELD_DECLARATION;
}
/**
* Lookup method for finding possible annotated order of property names
* for the type this introspector is to introspect
*
* @return List of property names that defines order (possibly partial); if
* none, empty List (but never null)
*/
protected List<String> _findNameSortOrder() {
JsonPropertyOrder ann = _find(_type, JsonPropertyOrder.class);
if (ann == null) {
return Collections.emptyList();
}
return Arrays.asList(ann.value());
}
private void checkJsonPropertyOrder(final boolean includeContextStack, final boolean includeContextMap,
final boolean includeStacktrace, final String str) {
final JsonPropertyOrder annotation = AbstractLogEventXmlMixIn.class.getAnnotation(JsonPropertyOrder.class);
Assert.assertNotNull(annotation);
int previousIndex = 0;
String previousName = null;
for (final String name : annotation.value()) {
final int currentIndex = str.indexOf(name);
if (!includeContextStack && XmlConstants.ELT_CONTEXT_STACK.equals(name)) {
Assert.assertTrue(String.format("Unexpected element '%s' in: %s", name, str),
currentIndex == NOT_FOUND);
break;
}
if (!includeContextMap && XmlConstants.ELT_CONTEXT_MAP.equals(name)) {
Assert.assertTrue(String.format("Unexpected element '%s' in: %s", name, str),
currentIndex == NOT_FOUND);
break;
}
if (!includeStacktrace && XmlConstants.ELT_EXTENDED_STACK_TRACE.equals(name)) {
Assert.assertTrue(String.format("Unexpected element '%s' in: %s", name, str),
currentIndex == NOT_FOUND);
break;
}
if (!includeStacktrace && XmlConstants.ELT_EXTENDED_STACK_TRACE_ITEM.equals(name)) {
Assert.assertTrue(String.format("Unexpected element '%s' in: %s", name, str),
currentIndex == NOT_FOUND);
break;
}
// TODO
// Bug: The method
// com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector._sortProperties(Map<String,
// POJOPropertyBuilder>) messes up the order defined in AbstractXmlLogEventMixIn's JsonPropertyOrder
// annotations.
// Assert.assertTrue(String.format("name='%s', previousIndex=%,d, previousName='%s', currentIndex=%,d: %s",
// name, previousIndex, previousName, currentIndex, str), previousIndex < currentIndex);
previousIndex = currentIndex;
previousName = name;
}
}
private Map<Element, TypeMirror> getOrderedFields(DeclaredType enclosingType) {
TypeElement enclosingElement = ((TypeElement) enclosingType.asElement());
TypeMirror superclass = enclosingElement.getSuperclass();
if (superclass.getKind().equals(TypeKind.NONE)) {
return new HashMap<>();
}
final List<Element> orderedProperties = new ArrayList<>();
final List<Element> enclosedFields = enclosingElement.getEnclosedElements().stream()
.filter(e -> ElementKind.FIELD.equals(e.getKind()) && isEligibleForSerializationDeserialization(e))
.collect(Collectors.toList());
Optional.ofNullable(typeUtils.asElement(beanType).getAnnotation(JsonPropertyOrder.class))
.ifPresent(jsonPropertyOrder -> {
final List<String> orderedFieldsNames = Arrays.asList(jsonPropertyOrder.value());
orderedProperties.addAll(enclosedFields.stream()
.filter(f -> orderedFieldsNames.contains(f.getSimpleName().toString()))
.collect(Collectors.toList()));
enclosedFields.removeAll(orderedProperties);
if (jsonPropertyOrder.alphabetic()) {
enclosedFields.sort(Comparator.comparing(f -> f.getSimpleName().toString()));
}
enclosedFields.addAll(0, orderedProperties);
});
List<? extends TypeParameterElement> typeParameters = enclosingElement.getTypeParameters();
List<? extends TypeMirror> typeArguments = enclosingType.getTypeArguments();
final Map<? extends TypeParameterElement, ? extends TypeMirror> typeParameterMap =
IntStream.range(0, typeParameters.size())
.boxed()
.collect(Collectors.toMap(typeParameters::get, typeArguments::get));
Map<Element, TypeMirror> res = enclosedFields.stream().collect(
Collectors.toMap(
fieldElement -> fieldElement,
fieldElement -> Type.getDeclaredType(fieldElement.asType(), typeParameterMap),
(u, v) -> {
throw new IllegalStateException(String.format("Duplicate key %s", u));
},
LinkedHashMap::new));
String typeErrs = res.entrySet().stream()
.filter(entry -> Type.hasTypeArgumentWithBoundedWildcards(entry.getValue()) || Type.hasUnboundedWildcards(entry.getValue()))
.map(entry -> "Member '" + entry.getKey().getSimpleName() + "' resolved type: '" + entry.getValue() + "'")
.collect(Collectors.joining("\n"));
if (!typeErrs.isEmpty())
throw new RuntimeException(
"Type: '" + enclosingType
+ "' could not have generic member of type parametrized with type argument having unbounded wildcards"
+ " or non-collections having type argument with bounded wildcards:\n"
+ typeErrs);
if (superclass.getKind() == TypeKind.DECLARED)
res.putAll(getOrderedFields((DeclaredType) Type.getDeclaredType(superclass, typeParameterMap)));
return res;
}
@Override
public void propertyOrder(JDefinedClass clazz, JsonNode propertiesNode) {
JAnnotationArrayMember annotationValue = clazz.annotate(JsonPropertyOrder.class).paramArray("value");
annotationValue.param("apiVersion");
annotationValue.param("kind");
annotationValue.param("metadata");
final Iterator<Map.Entry<String, JsonNode>> fields = propertiesNode.fields();
while (fields.hasNext()) {
final Map.Entry<String, JsonNode> entry = fields.next();
String key = entry.getKey();
switch (key) {
case "kind":
case "metadata":
case "apiVersion":
break;
case "deprecatedAllowOrigin":
key = "allowOrigin";
default:
annotationValue.param(key);
}
}
final String pkgName = clazz.getPackage().name();
final int i = pkgName.lastIndexOf('.');
final String version = pkgName.substring(i + 1);
if (version.startsWith("v")) {
final Optional<IstioSpecRegistry.CRDInfo> kind = IstioSpecRegistry.getCRDInfo(clazz.name(), version);
kind.ifPresent(k -> {
clazz._implements(IstioSpec.class);
clazz.annotate(IstioKind.class).param("name", k.getKind()).param("plural", k.getPlural());
clazz.annotate(IstioApiVersion.class).param("value", k.getAPIVersion());
});
}
clazz.annotate(ToString.class);
clazz.annotate(EqualsAndHashCode.class);
JAnnotationUse buildable = clazz.annotate(Buildable.class)
.param("editableEnabled", false)
.param("generateBuilderPackage", true)
.param("builderPackage", BUILDER_PACKAGE);
buildable.paramArray("inline").annotate(Inline.class)
.param("type", doneableClass)
.param("prefix", "Doneable")
.param("value", "done");
buildable.paramArray("refs").annotate(BuildableReference.class)
.param("value", objectMetaClass);
if (clazz.name().endsWith("Spec")) {
JAnnotationArrayMember arrayMember = clazz.annotate(VelocityTransformations.class)
.paramArray("value");
arrayMember.annotate(VelocityTransformation.class).param("value", "/istio-resource.vm");
arrayMember.annotate(VelocityTransformation.class).param("value", "/istio-resource-list.vm");
arrayMember.annotate(VelocityTransformation.class).param("value", "/istio-manifest.vm")
.param("outputPath", "crd.properties").param("gather", true);
arrayMember.annotate(VelocityTransformation.class).param("value", "/istio-mappings-provider.vm")
.param("outputPath", Paths.get("me", "snowdrop", "istio", "api", "model",
"IstioResourceMappingsProvider.java").toString())
.param("gather", true);
}
}
@Override
public void propertyOrder(JDefinedClass clazz, JsonNode propertiesNode) {
JAnnotationArrayMember annotationValue = clazz.annotate(JsonPropertyOrder.class).paramArray(ANNOTATION_VALUE);
annotationValue.param(API_VERSION);
annotationValue.param(KIND);
annotationValue.param(METADATA);
for (Iterator<String> properties = propertiesNode.fieldNames(); properties.hasNext();) {
String next = properties.next();
if (!next.equals(API_VERSION) && !next.equals(KIND) && !next.equals(METADATA)) {
annotationValue.param(next);
}
}
clazz.annotate(ToString.class);
clazz.annotate(EqualsAndHashCode.class);
processBuildable(clazz);
if (clazz.fields().containsKey(KIND) && clazz.fields().containsKey(METADATA)) {
String resourceName;
if (clazz.name().endsWith("List")) {
resourceName = clazz.name().substring(0, clazz.name().length() - 4);
pendingLists.put(resourceName, clazz);
} else {
resourceName = clazz.name();
pendingResources.put(clazz.name(), clazz);
}
if (pendingResources.containsKey(resourceName) && pendingLists.containsKey(resourceName)) {
JDefinedClass resourceClass = pendingResources.get(resourceName);
JDefinedClass resourceListClass = pendingLists.get(resourceName);
String apiVersion = propertiesNode.get(API_VERSION).get("default").toString().replaceAll(Pattern.quote("\""), "");
String apiGroup = "";
if (apiVersion.contains("/")) {
apiGroup = apiVersion.substring(0, apiVersion.lastIndexOf('/'));
apiVersion = apiVersion.substring(apiGroup.length() + 1);
}
String packageSuffix = getPackageSuffix(apiVersion);
resourceClass.annotate(ApiVersion.class).param(ANNOTATION_VALUE, apiVersion);
resourceClass.annotate(ApiGroup.class).param(ANNOTATION_VALUE, apiGroup);
resourceClass.annotate(PackageSuffix.class).param(ANNOTATION_VALUE, packageSuffix);
resourceListClass.annotate(ApiVersion.class).param(ANNOTATION_VALUE, apiVersion);
resourceListClass.annotate(ApiGroup.class).param(ANNOTATION_VALUE, apiGroup);
resourceListClass.annotate(PackageSuffix.class).param(ANNOTATION_VALUE, packageSuffix);
pendingLists.remove(resourceName);
pendingResources.remove(resourceName);
addClassesToPropertyFiles(resourceClass);
}
}
}
/**
* <p>processBean</p>
*
* @param logger a {@link com.google.gwt.core.ext.TreeLogger} object.
* @param typeOracle a {@link com.github.nmorel.gwtjackson.rebind.JacksonTypeOracle} object.
* @param configuration a {@link com.github.nmorel.gwtjackson.rebind.RebindConfiguration} object.
* @param beanType a {@link com.google.gwt.core.ext.typeinfo.JClassType} object.
* @return a {@link com.github.nmorel.gwtjackson.rebind.bean.BeanInfo} object.
* @throws com.google.gwt.core.ext.UnableToCompleteException if any.
*/
public static BeanInfo processBean( TreeLogger logger, JacksonTypeOracle typeOracle, RebindConfiguration configuration, JClassType
beanType ) throws UnableToCompleteException {
BeanInfoBuilder builder = new BeanInfoBuilder();
builder.setType( beanType );
if ( null != beanType.isGenericType() ) {
builder.setParameterizedTypes( Arrays.<JClassType>asList( beanType.isGenericType().getTypeParameters() ) );
}
determineInstanceCreator( configuration, typeOracle, logger, beanType, builder );
Optional<JsonAutoDetect> jsonAutoDetect = findFirstEncounteredAnnotationsOnAllHierarchy( configuration, beanType, JsonAutoDetect
.class );
if ( jsonAutoDetect.isPresent() ) {
builder.setCreatorVisibility( jsonAutoDetect.get().creatorVisibility() );
builder.setFieldVisibility( jsonAutoDetect.get().fieldVisibility() );
builder.setGetterVisibility( jsonAutoDetect.get().getterVisibility() );
builder.setIsGetterVisibility( jsonAutoDetect.get().isGetterVisibility() );
builder.setSetterVisibility( jsonAutoDetect.get().setterVisibility() );
}
Optional<JsonIgnoreProperties> jsonIgnoreProperties = findFirstEncounteredAnnotationsOnAllHierarchy( configuration, beanType,
JsonIgnoreProperties.class );
if ( jsonIgnoreProperties.isPresent() ) {
builder.setIgnoredFields( new LinkedHashSet<String>( Arrays.asList( jsonIgnoreProperties.get().value() ) ) );
builder.setIgnoreUnknown( jsonIgnoreProperties.get().ignoreUnknown() );
}
Optional<JsonPropertyOrder> jsonPropertyOrder = findFirstEncounteredAnnotationsOnAllHierarchy( configuration, beanType,
JsonPropertyOrder.class );
builder.setPropertyOrderAlphabetic( jsonPropertyOrder.isPresent() && jsonPropertyOrder.get().alphabetic() );
if ( jsonPropertyOrder.isPresent() && jsonPropertyOrder.get().value().length > 0 ) {
builder.setPropertyOrderList( Arrays.asList( jsonPropertyOrder.get().value() ) );
} else if ( !builder.getCreatorParameters().isEmpty() ) {
List<String> propertyOrderList = new ArrayList<String>( builder.getCreatorParameters().keySet() );
builder.setPropertyOrderList( propertyOrderList );
if ( builder.isPropertyOrderAlphabetic() ) {
Collections.sort( propertyOrderList );
}
}
Optional<JsonInclude> jsonInclude = findFirstEncounteredAnnotationsOnAllHierarchy( configuration, beanType,
JsonInclude.class );
if ( jsonInclude.isPresent() ) {
builder.setInclude( Optional.of( jsonInclude.get().value() ) );
}
builder.setIdentityInfo( processIdentity( logger, typeOracle, configuration, beanType ) );
builder.setTypeInfo( processType( logger, typeOracle, configuration, beanType ) );
return builder.build();
}
/**
* Determine whether the given type's properties that are not specifically mentioned in a {@link JsonPropertyOrder} annotation should be sorted
* alphabetically, based on {@link JsonPropertyOrder#alphabetic()}. If no such annotation is present, the value given in the
* {@link #JsonPropertySorter(boolean)} constructor.
*
* @param declaringType type for which the properties' default sorting should be determined
* @return whether properties that are not specifically mentioned in a {@link JsonPropertyOrder} annotation should be sorted alphabetically
*/
protected boolean shouldSortPropertiesAlphabetically(Class<?> declaringType) {
return Optional.ofNullable(declaringType.getAnnotation(JsonPropertyOrder.class))
.map(JsonPropertyOrder::alphabetic)
.orElse(this.sortAlphabeticallyIfNotAnnotated);
}