mirror of
https://github.com/fankes/moshi.git
synced 2025-10-20 00:19:21 +08:00
Add @Json.ignore
(#1417)
* Default Json.name to an unset value * Promote shared transient tests to DualKotlinTest * Add new ignore property to Json * Support it in ClassJsonAdapter * Mention no enum/record support * Support in KotlinJsonAdapter * Rework code gen API to know of "ignored" * Support in apt code gen * Support in KSP * Update old non-working transient example test * Synthetic holders * Use field on both
This commit is contained in:
@@ -134,6 +134,8 @@ final class ClassJsonAdapter<T> extends JsonAdapter<T> {
|
||||
boolean platformType = Util.isPlatformType(rawType);
|
||||
for (Field field : rawType.getDeclaredFields()) {
|
||||
if (!includeField(platformType, field.getModifiers())) continue;
|
||||
Json jsonAnnotation = field.getAnnotation(Json.class);
|
||||
if (jsonAnnotation != null && jsonAnnotation.ignore()) continue;
|
||||
|
||||
// Look up a type adapter for this type.
|
||||
Type fieldType = resolve(type, rawType, field.getGenericType());
|
||||
@@ -145,8 +147,10 @@ final class ClassJsonAdapter<T> extends JsonAdapter<T> {
|
||||
field.setAccessible(true);
|
||||
|
||||
// Store it using the field's name. If there was already a field with this name, fail!
|
||||
Json jsonAnnotation = field.getAnnotation(Json.class);
|
||||
String name = jsonAnnotation != null ? jsonAnnotation.name() : fieldName;
|
||||
String name =
|
||||
jsonAnnotation != null && !Json.UNSET_NAME.equals(jsonAnnotation.name())
|
||||
? jsonAnnotation.name()
|
||||
: fieldName;
|
||||
FieldBinding<Object> fieldBinding = new FieldBinding<>(name, field, adapter);
|
||||
FieldBinding<?> replaced = fieldBindings.put(name, fieldBinding);
|
||||
if (replaced != null) {
|
||||
|
@@ -29,8 +29,9 @@ import java.lang.annotation.Target;
|
||||
*
|
||||
* <ul>
|
||||
* <li><strong>Java class fields</strong>
|
||||
* <li><strong>Kotlin properties</strong> for use with {@code moshi-kotlin}. This includes both
|
||||
* properties declared in the constructor and properties declared as members.
|
||||
* <li><strong>Kotlin properties</strong> for use with {@code moshi-kotlin} or {@code
|
||||
* moshi-kotlin-codegen}. This includes both properties declared in the constructor and
|
||||
* properties declared as members.
|
||||
* </ul>
|
||||
*
|
||||
* <p>Users of the <a href="https://github.com/rharter/auto-value-moshi">AutoValue: Moshi
|
||||
@@ -39,5 +40,17 @@ import java.lang.annotation.Target;
|
||||
@Retention(RUNTIME)
|
||||
@Documented
|
||||
public @interface Json {
|
||||
String name();
|
||||
/** The default value of {@link #name()}. Should only be used to check if it's been set. */
|
||||
String UNSET_NAME = "\u0000";
|
||||
|
||||
/** The name of the field when encoded as JSON. */
|
||||
String name() default UNSET_NAME;
|
||||
|
||||
/**
|
||||
* If true, this field/property will be ignored. This is semantically similar to use of {@code
|
||||
* transient} on the JVM.
|
||||
*
|
||||
* <p><strong>Note:</strong> this has no effect in enums or record classes.
|
||||
*/
|
||||
boolean ignore() default false;
|
||||
}
|
||||
|
@@ -275,7 +275,10 @@ final class StandardJsonAdapters {
|
||||
for (int i = 0; i < constants.length; i++) {
|
||||
T constant = constants[i];
|
||||
Json annotation = enumType.getField(constant.name()).getAnnotation(Json.class);
|
||||
String name = annotation != null ? annotation.name() : constant.name();
|
||||
String name =
|
||||
annotation != null && !Json.UNSET_NAME.equals(annotation.name())
|
||||
? annotation.name()
|
||||
: constant.name();
|
||||
nameStrings[i] = name;
|
||||
}
|
||||
options = JsonReader.Options.of(nameStrings);
|
||||
|
@@ -91,7 +91,10 @@ final class RecordJsonAdapter<T> extends JsonAdapter<T> {
|
||||
Set<Annotation> qualifiers = null;
|
||||
for (var annotation : component.getDeclaredAnnotations()) {
|
||||
if (annotation instanceof Json jsonAnnotation) {
|
||||
jsonName = jsonAnnotation.name();
|
||||
var annotationName = jsonAnnotation.name();
|
||||
if (!Json.UNSET_NAME.equals(annotationName)) {
|
||||
jsonName = jsonAnnotation.name();
|
||||
}
|
||||
} else {
|
||||
if (annotation.annotationType().isAnnotationPresent(JsonQualifier.class)) {
|
||||
if (qualifiers == null) {
|
||||
|
@@ -153,6 +153,26 @@ public final class ClassJsonAdapterTest {
|
||||
assertThat(fromJson.b).isEqualTo(12);
|
||||
}
|
||||
|
||||
static class IgnoredFields {
|
||||
@Json(ignore = true)
|
||||
int a;
|
||||
|
||||
int b;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ignoredFieldsOmitted() throws Exception {
|
||||
IgnoredFields value = new IgnoredFields();
|
||||
value.a = 11;
|
||||
value.b = 12;
|
||||
String toJson = toJson(IgnoredFields.class, value);
|
||||
assertThat(toJson).isEqualTo("{\"b\":12}");
|
||||
|
||||
IgnoredFields fromJson = fromJson(IgnoredFields.class, "{\"a\":13,\"b\":12}");
|
||||
assertThat(fromJson.a).isEqualTo(0); // Not assigned.
|
||||
assertThat(fromJson.b).isEqualTo(12);
|
||||
}
|
||||
|
||||
static class BaseA {
|
||||
int a;
|
||||
}
|
||||
|
Reference in New Issue
Block a user