You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@johnzon.apache.org by rm...@apache.org on 2016/06/28 21:45:51 UTC
johnzon git commit: JOHNZON-87 meta annotation support
Repository: johnzon
Updated Branches:
refs/heads/master ab0b4af93 -> b28c4baa0
JOHNZON-87 meta annotation support
Project: http://git-wip-us.apache.org/repos/asf/johnzon/repo
Commit: http://git-wip-us.apache.org/repos/asf/johnzon/commit/b28c4baa
Tree: http://git-wip-us.apache.org/repos/asf/johnzon/tree/b28c4baa
Diff: http://git-wip-us.apache.org/repos/asf/johnzon/diff/b28c4baa
Branch: refs/heads/master
Commit: b28c4baa08536f012bbc7a8e5a544b005f3a723e
Parents: ab0b4af
Author: Romain manni-Bucau <rm...@gmail.com>
Authored: Tue Jun 28 23:45:37 2016 +0200
Committer: Romain manni-Bucau <rm...@gmail.com>
Committed: Tue Jun 28 23:45:37 2016 +0200
----------------------------------------------------------------------
.../apache/johnzon/jsonb/JsonbAccessMode.java | 30 ++--
.../org/apache/johnzon/mapper/JohnzonAny.java | 3 +-
.../apache/johnzon/mapper/JohnzonConverter.java | 3 +-
.../apache/johnzon/mapper/JohnzonIgnore.java | 3 +-
.../apache/johnzon/mapper/JohnzonProperty.java | 3 +-
.../johnzon/mapper/JohnzonVirtualObjects.java | 3 +-
.../johnzon/mapper/access/FieldAccessMode.java | 10 +-
.../org/apache/johnzon/mapper/access/Meta.java | 99 +++++++++++++
.../johnzon/mapper/access/MethodAccessMode.java | 10 +-
.../apache/johnzon/mapper/MetaMapperTest.java | 140 +++++++++++++++++++
10 files changed, 279 insertions(+), 25 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/johnzon/blob/b28c4baa/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JsonbAccessMode.java
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JsonbAccessMode.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JsonbAccessMode.java
index d41a98d..25bdf12 100644
--- a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JsonbAccessMode.java
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JsonbAccessMode.java
@@ -36,6 +36,7 @@ import org.apache.johnzon.mapper.access.AccessMode;
import org.apache.johnzon.mapper.access.BaseAccessMode;
import org.apache.johnzon.mapper.access.FieldAccessMode;
import org.apache.johnzon.mapper.access.FieldAndMethodAccessMode;
+import org.apache.johnzon.mapper.access.Meta;
import org.apache.johnzon.mapper.access.MethodAccessMode;
import org.apache.johnzon.mapper.converter.ReversedAdapter;
import org.apache.johnzon.mapper.internal.AdapterKey;
@@ -172,12 +173,12 @@ public class JsonbAccessMode implements AccessMode, Closeable {
itemConverters = new Adapter<?, ?>[types.length];
int i = 0;
for (final Parameter parameter : (finalConstructor == null ? finalFactory : finalConstructor).getParameters()) {
- final JsonbProperty property = parameter.getAnnotation(JsonbProperty.class);
+ final JsonbProperty property = getAnnotation(parameter, JsonbProperty.class);
params[i] = property != null ? property.value() : parameter.getName();
- final JsonbTypeAdapter adapter = parameter.getAnnotation(JsonbTypeAdapter.class);
- final JsonbDateFormat dateFormat = parameter.getAnnotation(JsonbDateFormat.class);
- final JsonbNumberFormat numberFormat = parameter.getAnnotation(JsonbNumberFormat.class);
+ final JsonbTypeAdapter adapter = getAnnotation(parameter, JsonbTypeAdapter.class);
+ final JsonbDateFormat dateFormat = getAnnotation(parameter, JsonbDateFormat.class);
+ final JsonbNumberFormat numberFormat = getAnnotation(parameter, JsonbNumberFormat.class);
if (adapter == null && dateFormat == null && numberFormat == null) {
converters[i] = defaultConverters.get(parameter.getType());
itemConverters[i] = null;
@@ -326,8 +327,8 @@ public class JsonbAccessMode implements AccessMode, Closeable {
private ParameterizedType findPt(final Class<?> value, final Class<?> type) {
return ParameterizedType.class.cast(
- Stream.of(value.getGenericInterfaces())
- .filter(i -> ParameterizedType.class.isInstance(i) && ParameterizedType.class.cast(i).getRawType() == type).findFirst().orElse(null));
+ Stream.of(value.getGenericInterfaces())
+ .filter(i -> ParameterizedType.class.isInstance(i) && ParameterizedType.class.cast(i).getRawType() == type).findFirst().orElse(null));
}
private JohnzonAdapterFactory.Instance newInstance(final Class<?> value) {
@@ -603,12 +604,12 @@ public class JsonbAccessMode implements AccessMode, Closeable {
return !(FieldAccessMode.FieldDecoratedType.class.isInstance(t) ?
visibility.isVisible(FieldAccessMode.FieldDecoratedType.class.cast(t).getField())
: (MethodAccessMode.MethodDecoratedType.class.isInstance(t) &&
- visibility.isVisible(MethodAccessMode.MethodDecoratedType.class.cast(t).getMethod())));
+ visibility.isVisible(MethodAccessMode.MethodDecoratedType.class.cast(t).getMethod())));
}
private Comparator<String> orderComparator(final Class<?> clazz) {
final Comparator<String> keyComparator;
- final JsonbPropertyOrder orderAnnotation = clazz.getAnnotation(JsonbPropertyOrder.class);
+ final JsonbPropertyOrder orderAnnotation = Meta.getAnnotation(clazz, JsonbPropertyOrder.class);
if (orderAnnotation != null) {
final List<String> indexed = new ArrayList<>(asList(orderAnnotation.value()));
keyComparator = (o1, o2) -> {
@@ -645,6 +646,15 @@ public class JsonbAccessMode implements AccessMode, Closeable {
toRelease.clear();
}
+ // belongs to Meta but java 8
+ private static <T extends Annotation> T getAnnotation(final Parameter param, final Class<T> api) {
+ final T annotation = param.getAnnotation(api);
+ if (annotation != null) {
+ return annotation;
+ }
+ return Meta.findMeta(param.getAnnotations(), api);
+ }
+
private class ReaderConverters {
private Adapter<?, ?> converter;
private ObjectConverter.Reader reader;
@@ -729,12 +739,12 @@ public class JsonbAccessMode implements AccessMode, Closeable {
@Override
public <T extends Annotation> T getAnnotation(final Class<T> clazz) {
- return annotations.getAnnotation(clazz);
+ return Meta.getAnnotation(annotations, clazz);
}
@Override
public <T extends Annotation> T getClassOrPackageAnnotation(final Class<T> clazz) {
- return null;
+ return Meta.getAnnotation(clazz.getPackage(), clazz);
}
@Override
http://git-wip-us.apache.org/repos/asf/johnzon/blob/b28c4baa/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/JohnzonAny.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/JohnzonAny.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/JohnzonAny.java
index b134de7..16338e3 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/JohnzonAny.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/JohnzonAny.java
@@ -21,10 +21,11 @@ package org.apache.johnzon.mapper;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Retention(RUNTIME)
-@Target(METHOD)
+@Target({METHOD, ANNOTATION_TYPE})
public @interface JohnzonAny {
}
http://git-wip-us.apache.org/repos/asf/johnzon/blob/b28c4baa/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/JohnzonConverter.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/JohnzonConverter.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/JohnzonConverter.java
index b298792..85a8f5f 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/JohnzonConverter.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/JohnzonConverter.java
@@ -21,12 +21,13 @@ package org.apache.johnzon.mapper;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
-@Target({ METHOD, FIELD, PARAMETER })
+@Target({ METHOD, FIELD, PARAMETER, ANNOTATION_TYPE })
@Retention(RUNTIME)
public @interface JohnzonConverter {
Class<? extends MapperConverter> value();
http://git-wip-us.apache.org/repos/asf/johnzon/blob/b28c4baa/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/JohnzonIgnore.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/JohnzonIgnore.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/JohnzonIgnore.java
index c589e58..a1f7d85 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/JohnzonIgnore.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/JohnzonIgnore.java
@@ -21,11 +21,12 @@ package org.apache.johnzon.mapper;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
-@Target({ METHOD, FIELD })
+@Target({ METHOD, FIELD, ANNOTATION_TYPE })
@Retention(RUNTIME)
public @interface JohnzonIgnore {
/**
http://git-wip-us.apache.org/repos/asf/johnzon/blob/b28c4baa/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/JohnzonProperty.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/JohnzonProperty.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/JohnzonProperty.java
index 327f9e3..9c7d554 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/JohnzonProperty.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/JohnzonProperty.java
@@ -21,11 +21,12 @@ package org.apache.johnzon.mapper;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
-@Target({ METHOD, FIELD })
+@Target({ METHOD, FIELD, ANNOTATION_TYPE })
@Retention(RUNTIME)
public @interface JohnzonProperty {
/**
http://git-wip-us.apache.org/repos/asf/johnzon/blob/b28c4baa/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/JohnzonVirtualObjects.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/JohnzonVirtualObjects.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/JohnzonVirtualObjects.java
index e539b10..a5e60d2 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/JohnzonVirtualObjects.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/JohnzonVirtualObjects.java
@@ -22,10 +22,11 @@ import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
-@Target(TYPE)
+@Target({ TYPE, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Inherited
public @interface JohnzonVirtualObjects {
http://git-wip-us.apache.org/repos/asf/johnzon/blob/b28c4baa/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAccessMode.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAccessMode.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAccessMode.java
index 81e0b5d..cff4358 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAccessMode.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAccessMode.java
@@ -41,7 +41,7 @@ public class FieldAccessMode extends BaseAccessMode {
final Map<String, Reader> readers = new HashMap<String, Reader>();
for (final Map.Entry<String, Field> f : fields(clazz).entrySet()) {
final String key = f.getKey();
- if (isIgnored(key) || f.getValue().getAnnotation(JohnzonAny.class) != null) {
+ if (isIgnored(key) || Meta.getAnnotation(f.getValue(), JohnzonAny.class) != null) {
continue;
}
@@ -67,7 +67,7 @@ public class FieldAccessMode extends BaseAccessMode {
}
private String extractKey(final Field f, final String key) {
- final JohnzonProperty property = f.getAnnotation(JohnzonProperty.class);
+ final JohnzonProperty property = Meta.getAnnotation(f, JohnzonProperty.class);
return property != null ? property.value() : key;
}
@@ -109,8 +109,8 @@ public class FieldAccessMode extends BaseAccessMode {
@Override
public <T extends Annotation> T getClassOrPackageAnnotation(final Class<T> clazz) {
final Class<?> declaringClass = field.getDeclaringClass();
- final T annotation = declaringClass.getAnnotation(clazz);
- return annotation == null ? declaringClass.getPackage().getAnnotation(clazz) : annotation;
+ final T annotation = Meta.getAnnotation(declaringClass, clazz);
+ return annotation == null ? Meta.getAnnotation(declaringClass.getPackage(), clazz) : annotation;
}
@Override
@@ -129,7 +129,7 @@ public class FieldAccessMode extends BaseAccessMode {
@Override
public <T extends Annotation> T getAnnotation(final Class<T> clazz) {
- return field.getAnnotation(clazz);
+ return Meta.getAnnotation(field, clazz);
}
@Override
http://git-wip-us.apache.org/repos/asf/johnzon/blob/b28c4baa/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/Meta.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/Meta.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/Meta.java
new file mode 100644
index 0000000..9e57c09
--- /dev/null
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/Meta.java
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.johnzon.mapper.access;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.HashMap;
+import java.util.Map;
+
+import static java.util.Arrays.asList;
+
+public final class Meta {
+ private Meta() {
+ // no-op
+ }
+
+ public static <T extends Annotation> T getAnnotation(final AccessibleObject holder, final Class<T> api) {
+ final T annotation = holder.getAnnotation(api);
+ if (annotation != null) {
+ return annotation;
+ }
+ return findMeta(holder.getAnnotations(), api);
+ }
+
+ public static <T extends Annotation> T getAnnotation(final Class<?> clazz, final Class<T> api) {
+ final T annotation = clazz.getAnnotation(api);
+ if (annotation != null) {
+ return annotation;
+ }
+ return findMeta(clazz.getAnnotations(), api);
+ }
+
+ public static <T extends Annotation> T getAnnotation(final Package pck, final Class<T> api) {
+ final T annotation = pck.getAnnotation(api);
+ if (annotation != null) {
+ return annotation;
+ }
+ return findMeta(pck.getAnnotations(), api);
+ }
+
+ public static <T extends Annotation> T findMeta(final Annotation[] annotations, final Class<T> api) {
+ for (final Annotation a : annotations) {
+ final Class<? extends Annotation> userType = a.annotationType();
+ final T aa = userType.getAnnotation(api);
+ if (aa != null) {
+ boolean overriden = false;
+ final Map<String, Method> mapping = new HashMap<String, Method>();
+ for (final Class<?> cm : asList(api, userType)) {
+ for (final Method m : cm.getMethods()) {
+ overriden = mapping.put(m.getName(), m) != null || overriden;
+ }
+ }
+ if (!overriden) {
+ return aa;
+ }
+ return api.cast(newAnnotation(mapping, a, aa));
+ }
+ }
+ return null;
+ }
+
+ private static <T extends Annotation> T newAnnotation(final Map<String, Method> methodMapping, final Annotation user, final T johnzon) {
+ return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class<?>[]{johnzon.annotationType()},
+ new InvocationHandler() {
+ @Override
+ public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
+ final Method m = methodMapping.get(method.getName());
+ try {
+ if (m.getDeclaringClass() == user.annotationType()) {
+ return m.invoke(user, args);
+ }
+ return m.invoke(johnzon, args);
+ } catch (final InvocationTargetException ite) {
+ throw ite.getTargetException();
+ }
+ }
+ });
+ }
+}
http://git-wip-us.apache.org/repos/asf/johnzon/blob/b28c4baa/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/MethodAccessMode.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/MethodAccessMode.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/MethodAccessMode.java
index 524123b..302b4f4 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/MethodAccessMode.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/MethodAccessMode.java
@@ -49,7 +49,7 @@ public class MethodAccessMode extends BaseAccessMode {
for (final PropertyDescriptor descriptor : propertyDescriptors) {
final Method readMethod = descriptor.getReadMethod();
if (readMethod != null && readMethod.getDeclaringClass() != Object.class) {
- if (isIgnored(descriptor.getName()) || readMethod.getAnnotation(JohnzonAny.class) != null) {
+ if (isIgnored(descriptor.getName()) || Meta.getAnnotation(readMethod, JohnzonAny.class) != null) {
continue;
}
readers.put(extractKey(descriptor), new MethodReader(readMethod, fixType(clazz, readMethod.getGenericReturnType())));
@@ -80,7 +80,7 @@ public class MethodAccessMode extends BaseAccessMode {
}
private String extractKey(final PropertyDescriptor f) {
- final JohnzonProperty property = f.getReadMethod() == null ? null : f.getReadMethod().getAnnotation(JohnzonProperty.class);
+ final JohnzonProperty property = f.getReadMethod() == null ? null : Meta.getAnnotation(f.getReadMethod(), JohnzonProperty.class);
return property != null ? property.value() : f.getName();
}
@@ -113,8 +113,8 @@ public class MethodAccessMode extends BaseAccessMode {
@Override
public <T extends Annotation> T getClassOrPackageAnnotation(final Class<T> clazz) {
final Class<?> declaringClass = method.getDeclaringClass();
- final T annotation = declaringClass.getAnnotation(clazz);
- return annotation == null ? declaringClass.getPackage().getAnnotation(clazz) : annotation;
+ final T annotation = Meta.getAnnotation(declaringClass, clazz);
+ return annotation == null ? Meta.getAnnotation(declaringClass.getPackage(), clazz) : annotation;
}
@Override
@@ -133,7 +133,7 @@ public class MethodAccessMode extends BaseAccessMode {
@Override
public <T extends Annotation> T getAnnotation(final Class<T> clazz) {
- return method.getAnnotation(clazz);
+ return Meta.getAnnotation(method, clazz);
}
@Override
http://git-wip-us.apache.org/repos/asf/johnzon/blob/b28c4baa/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MetaMapperTest.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MetaMapperTest.java b/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MetaMapperTest.java
new file mode 100644
index 0000000..ba6c000
--- /dev/null
+++ b/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MetaMapperTest.java
@@ -0,0 +1,140 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.johnzon.mapper;
+
+import org.junit.Test;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.util.Comparator;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+public class MetaMapperTest {
+ @Test
+ public void customMappingAPI() {
+ final Mapper mapper = new MapperBuilder().setAttributeOrder(new Comparator<String>() {
+ @Override
+ public int compare(final String o1, final String o2) {
+ return o1.compareTo(o2);
+ }
+ }).setAccessModeName("field").build();
+
+ final String expectedJson = "{\"id\":123456,\"name\":\"Johnzon Mapper\",\"overriden\":\"API Rocks\",\"set\":\"yes\"}";
+ final User expectedUser = new User();
+ expectedUser.setId(123456);
+ expectedUser.setName("Johnzon Mapper");
+ expectedUser.setName2("You will not see me");
+ expectedUser.setCustom("API Rocks");
+ expectedUser.setCustom2("yes");
+
+ assertEquals(expectedJson, mapper.writeObjectAsString(expectedUser));
+
+ final User u = mapper.readObject(expectedJson.substring(0, expectedJson.length() - 1) + ",\"name2\":\"should be null\"}", User.class);
+ assertEquals(expectedUser.getId(), u.getId());
+ assertEquals(expectedUser.getName(), u.getName());
+ assertEquals(expectedUser.getCustom(), u.getCustom());
+ assertNull(u.getName2());
+ }
+
+ public static class User {
+ @Id
+ private long id;
+
+ @Name
+ private String name;
+
+ @Custom
+ private String custom;
+
+ @Custom("set")
+ private String custom2;
+
+ @Ignored
+ private String name2;
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(final long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ public String getCustom() {
+ return custom;
+ }
+
+ public void setCustom(final String custom) {
+ this.custom = custom;
+ }
+
+ public String getName2() {
+ return name2;
+ }
+
+ public void setName2(final String name2) {
+ this.name2 = name2;
+ }
+
+ public String getCustom2() {
+ return custom2;
+ }
+
+ public void setCustom2(final String custom2) {
+ this.custom2 = custom2;
+ }
+ }
+
+ @Target(FIELD)
+ @Retention(RUNTIME)
+ @JohnzonProperty("id")
+ public @interface Id {
+ }
+
+ @Target(FIELD)
+ @Retention(RUNTIME)
+ @JohnzonIgnore
+ public @interface Ignored {
+ }
+
+ @Target(FIELD)
+ @Retention(RUNTIME)
+ @JohnzonProperty("name")
+ public @interface Name {
+ }
+
+ @Target(FIELD)
+ @Retention(RUNTIME)
+ @JohnzonProperty("ignored")
+ public @interface Custom {
+ String value() default "overriden";
+ }
+}