Skip to content

Commit fd48e04

Browse files
committed
provide NaN and Infinity in JsonWriter
Signed-off-by: Jorge Bescos Gascon <[email protected]>
1 parent f2ab7f1 commit fd48e04

File tree

6 files changed

+136
-24
lines changed

6 files changed

+136
-24
lines changed

impl/src/main/java/org/eclipse/parsson/JsonArrayBuilderImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ public int hashCode() {
473473
@Override
474474
public String toString() {
475475
StringWriter sw = new StringWriter();
476-
try (JsonWriter jw = new JsonWriterImpl(sw, bufferPool)) {
476+
try (JsonWriter jw = new JsonWriterImpl(sw, bufferPool, Collections.emptyMap())) {
477477
jw.write(this);
478478
}
479479
return sw.toString();

impl/src/main/java/org/eclipse/parsson/JsonObjectBuilderImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ public int hashCode() {
336336
@Override
337337
public String toString() {
338338
StringWriter sw = new StringWriter();
339-
try (JsonWriter jw = new JsonWriterImpl(sw, bufferPool)) {
339+
try (JsonWriter jw = new JsonWriterImpl(sw, bufferPool, Collections.emptyMap())) {
340340
jw.write(this);
341341
}
342342
return sw.toString();

impl/src/main/java/org/eclipse/parsson/JsonProviderImpl.java

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,14 +87,18 @@ public JsonGeneratorFactory createGeneratorFactory(Map<String, ?> config) {
8787
pool = bufferPool;
8888
} else {
8989
providerConfig = new HashMap<>();
90-
prettyPrinting = JsonProviderImpl.isPrettyPrintingEnabled(config);
90+
addKnowProperty(providerConfig, config, JsonGenerator.WRITE_NAN_AS_NULLS);
91+
addKnowProperty(providerConfig, config, JsonGenerator.WRITE_NAN_AS_STRINGS);
92+
if (prettyPrinting=JsonProviderImpl.isPrettyPrintingEnabled(config)) {
93+
// ?? It is set to true even if the property was false
94+
providerConfig.put(JsonGenerator.PRETTY_PRINTING, true);
95+
}
9196
pool = (BufferPool)config.get(BufferPool.class.getName());
9297
if (pool != null) {
9398
providerConfig.put(BufferPool.class.getName(), pool);
9499
} else {
95100
pool = bufferPool;
96101
}
97-
providerConfig.putAll(config);
98102
providerConfig = Collections.unmodifiableMap(providerConfig);
99103
}
100104

@@ -113,12 +117,12 @@ public JsonReader createReader(InputStream in) {
113117

114118
@Override
115119
public JsonWriter createWriter(Writer writer) {
116-
return new JsonWriterImpl(writer, bufferPool);
120+
return new JsonWriterImpl(writer, bufferPool, Collections.emptyMap());
117121
}
118122

119123
@Override
120124
public JsonWriter createWriter(OutputStream out) {
121-
return new JsonWriterImpl(out, bufferPool);
125+
return new JsonWriterImpl(out, bufferPool, Collections.emptyMap());
122126
}
123127

124128
@Override
@@ -132,7 +136,10 @@ public JsonWriterFactory createWriterFactory(Map<String, ?> config) {
132136
pool = bufferPool;
133137
} else {
134138
providerConfig = new HashMap<>();
139+
addKnowProperty(providerConfig, config, JsonGenerator.WRITE_NAN_AS_NULLS);
140+
addKnowProperty(providerConfig, config, JsonGenerator.WRITE_NAN_AS_STRINGS);
135141
if (prettyPrinting=JsonProviderImpl.isPrettyPrintingEnabled(config)) {
142+
// ?? It is set to true even if the property was false
136143
providerConfig.put(JsonGenerator.PRETTY_PRINTING, true);
137144
}
138145
pool = (BufferPool)config.get(BufferPool.class.getName());
@@ -279,6 +286,12 @@ public JsonBuilderFactory createBuilderFactory(Map<String, ?> config) {
279286
return new JsonBuilderFactoryImpl(pool, rejectDuplicateKeys);
280287
}
281288

289+
private void addKnowProperty(Map<String, Object> providerConfig, Map<String, ?> config, String property) {
290+
if (config.containsKey(property)) {
291+
providerConfig.put(property, config.get(property));
292+
}
293+
}
294+
282295
static boolean isPrettyPrintingEnabled(Map<String, ?> config) {
283296
return config.containsKey(JsonGenerator.PRETTY_PRINTING);
284297
}

impl/src/main/java/org/eclipse/parsson/JsonWriterFactoryImpl.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,17 +42,17 @@ class JsonWriterFactoryImpl implements JsonWriterFactory {
4242

4343
@Override
4444
public JsonWriter createWriter(Writer writer) {
45-
return new JsonWriterImpl(writer, prettyPrinting, bufferPool);
45+
return new JsonWriterImpl(writer, prettyPrinting, bufferPool, config);
4646
}
4747

4848
@Override
4949
public JsonWriter createWriter(OutputStream out) {
50-
return new JsonWriterImpl(out, prettyPrinting, bufferPool);
50+
return new JsonWriterImpl(out, prettyPrinting, bufferPool, config);
5151
}
5252

5353
@Override
5454
public JsonWriter createWriter(OutputStream out, Charset charset) {
55-
return new JsonWriterImpl(out, charset, prettyPrinting, bufferPool);
55+
return new JsonWriterImpl(out, charset, prettyPrinting, bufferPool, config);
5656
}
5757

5858
@Override

impl/src/main/java/org/eclipse/parsson/JsonWriterImpl.java

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import java.io.Writer;
2323
import java.nio.charset.Charset;
2424
import java.nio.charset.StandardCharsets;
25-
import java.util.Collections;
2625
import java.util.Map;
2726

2827
import org.eclipse.parsson.api.BufferPool;
@@ -44,33 +43,33 @@ class JsonWriterImpl implements JsonWriter {
4443
private boolean writeDone;
4544
private final NoFlushOutputStream os;
4645

47-
JsonWriterImpl(Writer writer, BufferPool bufferPool) {
48-
this(writer, false, bufferPool);
46+
JsonWriterImpl(Writer writer, BufferPool bufferPool, Map<String, ?> config) {
47+
this(writer, false, bufferPool, config);
4948
}
5049

51-
JsonWriterImpl(Writer writer, boolean prettyPrinting, BufferPool bufferPool) {
50+
JsonWriterImpl(Writer writer, boolean prettyPrinting, BufferPool bufferPool, Map<String, ?> config) {
5251
generator = prettyPrinting
53-
? new JsonPrettyGeneratorImpl(writer, bufferPool, Collections.emptyMap())
54-
: new JsonGeneratorImpl(writer, bufferPool, Collections.emptyMap());
52+
? new JsonPrettyGeneratorImpl(writer, bufferPool, config)
53+
: new JsonGeneratorImpl(writer, bufferPool, config);
5554
os = null;
5655
}
5756

58-
JsonWriterImpl(OutputStream out, BufferPool bufferPool) {
59-
this(out, StandardCharsets.UTF_8, false, bufferPool);
57+
JsonWriterImpl(OutputStream out, BufferPool bufferPool, Map<String, ?> config) {
58+
this(out, StandardCharsets.UTF_8, false, bufferPool, config);
6059
}
6160

62-
JsonWriterImpl(OutputStream out, boolean prettyPrinting, BufferPool bufferPool) {
63-
this(out, StandardCharsets.UTF_8, prettyPrinting, bufferPool);
61+
JsonWriterImpl(OutputStream out, boolean prettyPrinting, BufferPool bufferPool, Map<String, ?> config) {
62+
this(out, StandardCharsets.UTF_8, prettyPrinting, bufferPool, config);
6463
}
6564

6665
JsonWriterImpl(OutputStream out, Charset charset,
67-
boolean prettyPrinting, BufferPool bufferPool) {
66+
boolean prettyPrinting, BufferPool bufferPool, Map<String, ?> config) {
6867
// Decorating the given stream, so that buffered contents can be
6968
// written without actually flushing the stream.
7069
this.os = new NoFlushOutputStream(out);
7170
generator = prettyPrinting
72-
? new JsonPrettyGeneratorImpl(os, charset, bufferPool, Collections.emptyMap())
73-
: new JsonGeneratorImpl(os, charset, bufferPool, Collections.emptyMap());
71+
? new JsonPrettyGeneratorImpl(os, charset, bufferPool, config)
72+
: new JsonGeneratorImpl(os, charset, bufferPool, config);
7473
}
7574

7675
@Override

impl/src/test/java/org/eclipse/parsson/tests/JsonWriterTest.java

Lines changed: 102 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,20 @@
1616

1717
package org.eclipse.parsson.tests;
1818

19-
import jakarta.json.*;
2019
import java.io.ByteArrayOutputStream;
2120
import java.io.IOException;
2221
import java.io.StringWriter;
23-
22+
import java.util.HashMap;
23+
import java.util.Map;
24+
25+
import jakarta.json.Json;
26+
import jakarta.json.JsonArray;
27+
import jakarta.json.JsonObject;
28+
import jakarta.json.JsonValue;
29+
import jakarta.json.JsonWriter;
30+
import jakarta.json.JsonWriterFactory;
31+
import jakarta.json.stream.JsonGenerator;
32+
import jakarta.json.stream.JsonGeneratorFactory;
2433
import junit.framework.TestCase;
2534

2635
/**
@@ -214,6 +223,97 @@ public void testClose() throws Exception {
214223
assertTrue(baos.isClosed());
215224
}
216225

226+
private String nameValueNanInfinity(JsonWriterFactory writerFactory) {
227+
StringWriter writer = new StringWriter();
228+
JsonWriter jsonWriter = writerFactory.createWriter(writer);
229+
JsonObject jsonObject = Json.createObjectBuilder()
230+
.add("val1", Double.NaN)
231+
.add("val2", 1.0)
232+
.add("val3", 0.0)
233+
.add("val4", Double.POSITIVE_INFINITY)
234+
.add("val5", Double.NEGATIVE_INFINITY)
235+
.add("val6", Json.createValue(Double.NaN))
236+
.add("val7", Json.createValue(1.0))
237+
.add("val8", Json.createValue(0.0))
238+
.add("val9", Json.createValue(Double.POSITIVE_INFINITY))
239+
.add("val10", Json.createValue(Double.NEGATIVE_INFINITY)).build();
240+
jsonWriter.writeObject(jsonObject);
241+
jsonWriter.close();
242+
return writer.toString();
243+
}
244+
245+
private String jsonNumberNanInfinity(JsonWriterFactory writerFactory, double value) {
246+
StringWriter writer = new StringWriter();
247+
JsonWriter jsonWriter = writerFactory.createWriter(writer);
248+
jsonWriter.write(Json.createValue(value));
249+
jsonWriter.close();
250+
return writer.toString();
251+
}
252+
253+
public void testNanInfinityDefault() {
254+
Map<String, Object> config = new HashMap<>();
255+
JsonWriterFactory writerFactory = Json.createWriterFactory(config);
256+
assertEquals("{\"val1\":null,\"val2\":1.0,\"val3\":0.0,\"val4\":null,\"val5\":null,\"val6\":null,\"val7\":1.0,\"val8\":0.0,\"val9\":null,\"val10\":null}", nameValueNanInfinity(writerFactory));
257+
assertEquals("0.0", jsonNumberNanInfinity(writerFactory, 0.0));
258+
assertEquals("1.0", jsonNumberNanInfinity(writerFactory, 1.0));
259+
assertEquals("null", jsonNumberNanInfinity(writerFactory, Double.NaN));
260+
assertEquals("null", jsonNumberNanInfinity(writerFactory, Double.POSITIVE_INFINITY));
261+
assertEquals("null", jsonNumberNanInfinity(writerFactory, Double.NEGATIVE_INFINITY));
262+
}
263+
264+
public void testNanInfinityWriteNanAsNull() {
265+
Map<String, Object> config = new HashMap<>();
266+
config.put(JsonGenerator.WRITE_NAN_AS_NULLS, true);
267+
JsonWriterFactory writerFactory = Json.createWriterFactory(config);
268+
assertEquals("{\"val1\":null,\"val2\":1.0,\"val3\":0.0,\"val4\":null,\"val5\":null,\"val6\":null,\"val7\":1.0,\"val8\":0.0,\"val9\":null,\"val10\":null}", nameValueNanInfinity(writerFactory));
269+
assertEquals("0.0", jsonNumberNanInfinity(writerFactory, 0.0));
270+
assertEquals("1.0", jsonNumberNanInfinity(writerFactory, 1.0));
271+
assertEquals("null", jsonNumberNanInfinity(writerFactory, Double.NaN));
272+
assertEquals("null", jsonNumberNanInfinity(writerFactory, Double.POSITIVE_INFINITY));
273+
assertEquals("null", jsonNumberNanInfinity(writerFactory, Double.NEGATIVE_INFINITY));
274+
}
275+
276+
public void testNanInfinityWriteNanAsString() {
277+
Map<String, Object> config = new HashMap<>();
278+
config.put(JsonGenerator.WRITE_NAN_AS_STRINGS, true);
279+
JsonWriterFactory writerFactory = Json.createWriterFactory(config);
280+
assertEquals("{\"val1\":\"NaN\",\"val2\":1.0,\"val3\":0.0,\"val4\":\"+Infinity\",\"val5\":\"-Infinity\",\"val6\":\"NaN\",\"val7\":1.0,\"val8\":0.0,\"val9\":\"+Infinity\",\"val10\":\"-Infinity\"}", nameValueNanInfinity(writerFactory));
281+
assertEquals("0.0", jsonNumberNanInfinity(writerFactory, 0.0));
282+
assertEquals("1.0", jsonNumberNanInfinity(writerFactory, 1.0));
283+
assertEquals("\"NaN\"", jsonNumberNanInfinity(writerFactory, Double.NaN));
284+
assertEquals("\"+Infinity\"", jsonNumberNanInfinity(writerFactory, Double.POSITIVE_INFINITY));
285+
assertEquals("\"-Infinity\"", jsonNumberNanInfinity(writerFactory, Double.NEGATIVE_INFINITY));
286+
}
287+
288+
public void testNanInfinityBothFalse() {
289+
Map<String, Object> config = new HashMap<>();
290+
config.put(JsonGenerator.WRITE_NAN_AS_STRINGS, false);
291+
config.put(JsonGenerator.WRITE_NAN_AS_NULLS, false);
292+
JsonWriterFactory writerFactory = Json.createWriterFactory(config);
293+
try {
294+
nameValueNanInfinity(writerFactory);
295+
fail("Expected a failure");
296+
} catch (NumberFormatException e) {}
297+
try {
298+
jsonNumberNanInfinity(writerFactory, Double.NaN);
299+
fail("Expected a failure");
300+
} catch (NumberFormatException e) {}
301+
assertEquals("0.0", jsonNumberNanInfinity(writerFactory, 0.0));
302+
assertEquals("1.0", jsonNumberNanInfinity(writerFactory, 1.0));
303+
}
304+
305+
public void testNanInfinityBothTrue() {
306+
Map<String, Object> config = new HashMap<>();
307+
config.put(JsonGenerator.WRITE_NAN_AS_STRINGS, true);
308+
config.put(JsonGenerator.WRITE_NAN_AS_NULLS, true);
309+
JsonWriterFactory writerFactory = Json.createWriterFactory(config);
310+
assertEquals("{\"val1\":null,\"val2\":1.0,\"val3\":0.0,\"val4\":null,\"val5\":null,\"val6\":null,\"val7\":1.0,\"val8\":0.0,\"val9\":null,\"val10\":null}", nameValueNanInfinity(writerFactory));
311+
assertEquals("0.0", jsonNumberNanInfinity(writerFactory, 0.0));
312+
assertEquals("1.0", jsonNumberNanInfinity(writerFactory, 1.0));
313+
assertEquals("null", jsonNumberNanInfinity(writerFactory, Double.NaN));
314+
assertEquals("null", jsonNumberNanInfinity(writerFactory, Double.POSITIVE_INFINITY));
315+
assertEquals("null", jsonNumberNanInfinity(writerFactory, Double.NEGATIVE_INFINITY));
316+
}
217317
private static final class MyByteStream extends ByteArrayOutputStream {
218318
boolean closed;
219319

0 commit comments

Comments
 (0)