Skip to content

Commit 58ce4c0

Browse files
authored
Add support for ignoring nulls in JsonDataEncoder (#1175)
* Add support for ignoring nulls in JsonDataEncoder * Change 'ignoreNulls' to 'ignoreNullValues' * Add to API file and bump version * Replace dynamic dispatch with simpler 'if' check * Remove interface
1 parent 30f71bb commit 58ce4c0

File tree

5 files changed

+81
-10
lines changed

5 files changed

+81
-10
lines changed

encoders/firebase-encoders-json/api.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ package com.google.firebase.encoders.json {
7272
ctor public JsonDataEncoderBuilder();
7373
method @NonNull public com.google.firebase.encoders.DataEncoder build();
7474
method @NonNull public com.google.firebase.encoders.json.JsonDataEncoderBuilder configureWith(@NonNull com.google.firebase.encoders.config.Configurator);
75+
method @NonNull public com.google.firebase.encoders.json.JsonDataEncoderBuilder ignoreNullValues(boolean);
7576
method @NonNull public <T> com.google.firebase.encoders.json.JsonDataEncoderBuilder registerEncoder(@NonNull Class<T>, @NonNull com.google.firebase.encoders.ObjectEncoder<? super T>);
7677
method @NonNull public <T> com.google.firebase.encoders.json.JsonDataEncoderBuilder registerEncoder(@NonNull Class<T>, @NonNull com.google.firebase.encoders.ValueEncoder<? super T>);
7778
method @NonNull public com.google.firebase.encoders.json.JsonDataEncoderBuilder registerFallbackEncoder(@NonNull com.google.firebase.encoders.ObjectEncoder<java.lang.Object>);

encoders/firebase-encoders-json/gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
version=16.0.1
15+
version=16.1.0

encoders/firebase-encoders-json/src/json/java/com/google/firebase/encoders/json/JsonDataEncoderBuilder.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535

3636
public final class JsonDataEncoderBuilder implements EncoderConfig<JsonDataEncoderBuilder> {
3737

38-
private final ObjectEncoder<Object> DEFAULT_FALLBACK_ENCODER =
38+
private static final ObjectEncoder<Object> DEFAULT_FALLBACK_ENCODER =
3939
(o, ctx) -> {
4040
throw new EncodingException(
4141
"Couldn't find encoder for type " + o.getClass().getCanonicalName());
@@ -44,6 +44,7 @@ public final class JsonDataEncoderBuilder implements EncoderConfig<JsonDataEncod
4444
private final Map<Class<?>, ObjectEncoder<?>> objectEncoders = new HashMap<>();
4545
private final Map<Class<?>, ValueEncoder<?>> valueEncoders = new HashMap<>();
4646
private ObjectEncoder<Object> fallbackEncoder = DEFAULT_FALLBACK_ENCODER;
47+
private boolean ignoreNullValues = false;
4748

4849
private static final class TimestampEncoder implements ValueEncoder<Date> {
4950
private static final DateFormat rfc339;
@@ -104,6 +105,12 @@ public JsonDataEncoderBuilder configureWith(@NonNull Configurator config) {
104105
return this;
105106
}
106107

108+
@NonNull
109+
public JsonDataEncoderBuilder ignoreNullValues(boolean ignore) {
110+
this.ignoreNullValues = ignore;
111+
return this;
112+
}
113+
107114
@NonNull
108115
public DataEncoder build() {
109116
return new DataEncoder() {
@@ -112,7 +119,7 @@ public void encode(@NonNull Object o, @NonNull Writer writer)
112119
throws IOException, EncodingException {
113120
JsonValueObjectEncoderContext encoderContext =
114121
new JsonValueObjectEncoderContext(
115-
writer, objectEncoders, valueEncoders, fallbackEncoder);
122+
writer, objectEncoders, valueEncoders, fallbackEncoder, ignoreNullValues);
116123
encoderContext.add(o, false);
117124
encoderContext.close();
118125
}

encoders/firebase-encoders-json/src/json/java/com/google/firebase/encoders/json/JsonValueObjectEncoderContext.java

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,36 +37,37 @@ final class JsonValueObjectEncoderContext implements ObjectEncoderContext, Value
3737
private final Map<Class<?>, ObjectEncoder<?>> objectEncoders;
3838
private final Map<Class<?>, ValueEncoder<?>> valueEncoders;
3939
private final ObjectEncoder<Object> fallbackEncoder;
40+
private final boolean ignoreNullValues;
4041

4142
JsonValueObjectEncoderContext(
4243
@NonNull Writer writer,
4344
@NonNull Map<Class<?>, ObjectEncoder<?>> objectEncoders,
4445
@NonNull Map<Class<?>, ValueEncoder<?>> valueEncoders,
45-
ObjectEncoder<Object> fallbackEncoder) {
46+
ObjectEncoder<Object> fallbackEncoder,
47+
boolean ignoreNullValues) {
4648
this.jsonWriter = new JsonWriter(writer);
4749
this.objectEncoders = objectEncoders;
4850
this.valueEncoders = valueEncoders;
4951
this.fallbackEncoder = fallbackEncoder;
52+
this.ignoreNullValues = ignoreNullValues;
5053
}
5154

5255
private JsonValueObjectEncoderContext(JsonValueObjectEncoderContext anotherContext) {
5356
this.jsonWriter = anotherContext.jsonWriter;
5457
this.objectEncoders = anotherContext.objectEncoders;
5558
this.valueEncoders = anotherContext.valueEncoders;
5659
this.fallbackEncoder = anotherContext.fallbackEncoder;
60+
this.ignoreNullValues = anotherContext.ignoreNullValues;
5761
}
5862

5963
@NonNull
6064
@Override
6165
public JsonValueObjectEncoderContext add(@NonNull String name, @Nullable Object o)
6266
throws IOException, EncodingException {
63-
maybeUnNest();
64-
jsonWriter.name(name);
65-
if (o == null) {
66-
jsonWriter.nullValue();
67-
return this;
67+
if (ignoreNullValues) {
68+
return internalAddIgnoreNullValues(name, o);
6869
}
69-
return add(o, false);
70+
return internalAdd(name, o);
7071
}
7172

7273
@NonNull
@@ -311,4 +312,25 @@ private void maybeUnNest() throws IOException {
311312
jsonWriter.endObject();
312313
}
313314
}
315+
316+
private JsonValueObjectEncoderContext internalAdd(@NonNull String name, @Nullable Object o)
317+
throws IOException, EncodingException {
318+
maybeUnNest();
319+
jsonWriter.name(name);
320+
if (o == null) {
321+
jsonWriter.nullValue();
322+
return this;
323+
}
324+
return add(o, false);
325+
}
326+
327+
private JsonValueObjectEncoderContext internalAddIgnoreNullValues(
328+
@NonNull String name, @Nullable Object o) throws IOException, EncodingException {
329+
if (o == null) {
330+
return this;
331+
}
332+
maybeUnNest();
333+
jsonWriter.name(name);
334+
return add(o, false);
335+
}
314336
}

encoders/firebase-encoders-json/src/test/java/com/google/firebase/encoders/json/JsonDataEncoderBuilderTests.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import com.google.firebase.encoders.ObjectEncoderContext;
2323
import com.google.firebase.encoders.ValueEncoderContext;
2424
import java.util.Collections;
25+
import java.util.HashMap;
2526
import org.junit.Test;
2627
import org.junit.runner.RunWith;
2728

@@ -61,4 +62,44 @@ public void configureWith_shouldCorrectlyRegisterValueEncoder() throws EncodingE
6162
assertThat(encoder.encode(Collections.singletonMap("foo", new Foo())))
6263
.isEqualTo("{\"foo\":\"value\"}");
6364
}
65+
66+
@Test
67+
public void ignoreNullValues_shouldCorrectlyEncodeObjectIgnoringNullObjects()
68+
throws EncodingException {
69+
DataEncoder encoder =
70+
new JsonDataEncoderBuilder()
71+
.configureWith(
72+
cfg ->
73+
cfg.registerEncoder(
74+
Foo.class,
75+
(Foo s, ObjectEncoderContext ctx) -> {
76+
ctx.add("foo", "value");
77+
ctx.add("bar", null);
78+
}))
79+
.ignoreNullValues(true)
80+
.build();
81+
82+
assertThat(encoder.encode(new Foo())).isEqualTo("{\"foo\":\"value\"}");
83+
}
84+
85+
@Test
86+
public void ignoreNullValues_shouldCorrectlyEncodeValueIgnoringNullObjects()
87+
throws EncodingException {
88+
DataEncoder encoder =
89+
new JsonDataEncoderBuilder()
90+
.configureWith(
91+
cfg ->
92+
cfg.registerEncoder(
93+
Foo.class,
94+
(Foo s, ValueEncoderContext ctx) -> {
95+
ctx.add("value");
96+
}))
97+
.ignoreNullValues(true)
98+
.build();
99+
100+
HashMap<String, Foo> fooMap = new HashMap<>();
101+
fooMap.put("foo", new Foo());
102+
fooMap.put("bar", null);
103+
assertThat(encoder.encode(fooMap)).isEqualTo("{\"foo\":\"value\"}");
104+
}
64105
}

0 commit comments

Comments
 (0)