I try to avoid using null. I want to use Moshi to convert a class to/from JSON which contains Optional<?>:
class MyRequest {
Optional<Integer> id;
Optional<Integer> group;
}
Moshi complains: java.lang.IllegalArgumentException: Platform class java.util.Optional in java.util.Optional<java.lang.String> requires explicit JsonAdapter to be registered.
How about adding support for it in Moshi?
Any reason you can't just write an adapter for it per the message?
I don't want to write an adapter. Here are the reasons why:
Moshi supports List<T>. Why shouldn't it also support Optional<T>? Optional appeared 7 years ago in Java 8.
I would also ask for ImmutableList support. Code is easier to maintain when it uses immutable data structures by default.
List maps to a fundamental type in JSON: arrays. You can't just pick arbitrary types and ask why they aren't supported even though they're built in. We also don't support Set, for example.
Supporting Optional means we force Android users to a fairly high minimum supported version or to enable coreLibraryDesugaring. We also could conditionally install an adapter for it based on whether classloading the type throws or not.
We definitely aren't going to add support for Guava types. Someone can write a third-party library with adapters for its numerous collection APIs.
No action to take on this. Writing your own Optional adapter is trivial, here's one you and the rest of society can copy. Or you can put it into your own library that depends on Moshi and share it with the rest of society, there are a lot of little libraries like this!
public final class OptionalFactory implements JsonAdapter.Factory {
@Nullable
@Override
public JsonAdapter<?> create(Type type, Set<? extends Annotation> annotations, Moshi moshi) {
if (!annotations.isEmpty()) return null;
if (!(type instanceof ParameterizedType)) return null;
Class<?> rawType = Types.getRawType(type);
if (rawType != Optional.class) return null;
Type optionalType = ((ParameterizedType) type).getActualTypeArguments()[0];
JsonAdapter<?> optionalTypeAdapter = moshi.adapter(optionalType).nullSafe();
return new OptionalJsonAdapter<>(optionalTypeAdapter);
}
private static class OptionalJsonAdapter<T> extends JsonAdapter<Optional<T>> {
private final JsonAdapter<T> optionalTypeAdapter;
public OptionalJsonAdapter(JsonAdapter<T> optionalTypeAdapter) {
this.optionalTypeAdapter = optionalTypeAdapter;
}
@Nullable
@Override
public Optional<T> fromJson(JsonReader reader) throws IOException {
T instance = optionalTypeAdapter.fromJson(reader);
return Optional.ofNullable(instance);
}
@Override
public void toJson(JsonWriter writer, @Nullable Optional<T> value) throws IOException {
if (value.isPresent()) {
optionalTypeAdapter.toJson(writer, value.get());
} else {
writer.nullValue();
}
}
}
}
Thank you both for your work on Moshi. It solves a problem for me and helps get me closer to launching my product. It also improves my opinion of Square. I have a friend who works there. I have eaten with him in the Square SF office. I consider working at Square each time I look for a job.
@ZacSweers Thanks for providing an example. It is 45-lines and 1.3KB of code. With tests, it will be 2x or 3x bigger. In my opinion, that is not a trivial amount of code to maintain.
@JakeWharton Thanks for telling me about the limitations of Android users.
List maps to a fundamental type in JSON: arrays. You can't just pick arbitrary types and ask why they aren't supported even though they're built in. We also don't support Set, for example.
To clarify, I asked only for Optional.
I avoid using null and so do many other people. Language maintainers are adding support for this coding style because so many people want it:
null.Option is used throughout the standard library and all third-party libraries, including the JSON serialization library serde_json.null to Option::None. See https://stackoverflow.com/questions/44205435.pointer type requires using the unsafe keyword._Nullable and _Nonnull type annotationsT.nilable() type annotationOptional and Union[X, None] type annotationsNOT NULL constraintOptional@NonNull@Nullable proposed, implemented, and supported well by tooling.I understand if you personally like using null in your Java code. It's your code and you can write it however you wish. Please understand that others have different needs and want different things. Please try to exercise empathy with your users. Help us to use your library with our coding styles.
Sincerely,
Michael
List maps to a fundamental type in JSON: arrays. You can't just pick arbitrary types and ask why they aren't supported even though they're built in. We also don't support Set, for example.
To clarify, I asked only for Optional.
Your intent was clear. Perhaps you recall asking it as a question:
Moshi supports List
. Why shouldn't it also support Optional ?
I merely obliged and answered.
Anyway despite your tone I'm supportive of this.
Most helpful comment
No action to take on this. Writing your own
Optionaladapter is trivial, here's one you and the rest of society can copy. Or you can put it into your own library that depends on Moshi and share it with the rest of society, there are a lot of little libraries like this!