-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Default Value for Missing fields in Json #1005
Comments
Are there any advantages for such an approach? |
@lyubomyr-shaydariv if your question is why one need such functionality as part of Gson library, then my answer would be, my library should be able to initialize default values in the objects. If your question is around to change the approach to achieve the same functionality, I am open to suggestions and we can improve upon the approach. FYI, I created a pull request for this as well. |
All you need to cover such a case is a custom type adapter: missing final class PostProcessingTypeAdapterFactory
implements TypeAdapterFactory {
private final Iterable<? extends Consumer<Object>> postProcessors;
private PostProcessingTypeAdapterFactory(final Iterable<? extends Consumer<Object>> postProcessors) {
this.postProcessors = postProcessors;
}
static TypeAdapterFactory getPostProcessingTypeAdapterFactory(final Consumer<Object>... postProcessors) {
return new PostProcessingTypeAdapterFactory(asList(postProcessors.clone()));
}
static TypeAdapterFactory getPostProcessingTypeAdapterFactory(final Iterable<? extends Consumer<Object>> postProcessors) {
return new PostProcessingTypeAdapterFactory(postProcessors);
}
@Override
public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken) {
final TypeAdapter<T> delegateAdapter = gson.getDelegateAdapter(this, typeToken);
return new TypeAdapter<T>() {
@Override
public void write(final JsonWriter out, final T value)
throws IOException {
delegateAdapter.write(out, value);
}
@Override
public T read(final JsonReader in)
throws IOException {
final T value = delegateAdapter.read(in);
for ( final Consumer<Object> postProcessor : postProcessors ) {
postProcessor.accept(value);
}
return value;
}
};
}
} // This processor can be strategy-driven, but implemented stupid-simple just for the demo
final class VerySimpleMissingFieldsPostProcessor
implements Consumer<Object> {
private static final Consumer<Object> verySimpleMissingFieldsPostProcessor = new VerySimpleMissingFieldsPostProcessor();
private VerySimpleMissingFieldsPostProcessor() {
}
static Consumer<Object> getVerySimpleMissingFieldsPostProcessor() {
return verySimpleMissingFieldsPostProcessor;
}
@Override
public void accept(final Object o) {
try {
if ( o instanceof Foo ) {
final Field[] declaredFields = Foo.class.getDeclaredFields();
for ( final Field field : declaredFields ) {
if ( field.getType() == Optional.class ) {
field.setAccessible(true);
if ( field.get(o) == null ) {
field.set(o, Optional.empty());
}
}
}
}
} catch ( final IllegalAccessException ex ) {
throw new RuntimeException(ex);
}
}
} final class Foo {
String bar;
Optional<String> baz;
} final Gson gson = new GsonBuilder()
.registerTypeAdapterFactory(getPostProcessingTypeAdapterFactory(getVerySimpleMissingFieldsPostProcessor()))
.create();
final Foo foo = gson.fromJson("{\"bar\":\"bar-value\"}", Foo.class);
System.out.println(foo.bar);
System.out.println(foo.baz.orElse("missing!")); // no NPE Output:
|
Vote for the issue. I was hoping to fix that for type adapters. For example, I have an |
+1 for the feature (I want Collections to default to empty not null). For the record I looked at your PR. I'm not keen on baking that defaultType registry into the core builder at all. Better would be to detect a missing field (as the object is ended) and supply to the TypeAdapters as if it were explicitly null. This small change allows the rest of the chain-of-responsibility handling to process a null according to existing rules. It would be very simple to write some delegating I'd PR this myself but I'm not blind to the number of ignored PRs here. |
How do I set a field up with the expected value? I am currently getting |
Not a maintainer, but are you interested in this only for types where If only the former is the case maybe one solution would be to add a Or similar to #1005 (comment) maybe add a field annotation (e.g. |
This would be even more useful now, as the current workaround modifies the already constructed object and is therefore incompatible with records. |
I know, We can achieve this by just setting up the field with the expected value, but people may not always remember that. Can Gson provide us with some mechanism of handling the fields which are not present in JSON?
The text was updated successfully, but these errors were encountered: