Skip to content

Commit

Permalink
provide NaN and Infinity in JsonWriter
Browse files Browse the repository at this point in the history
Signed-off-by: Jorge Bescos Gascon <[email protected]>
  • Loading branch information
jbescos committed Sep 24, 2021
1 parent f2ab7f1 commit fd48e04
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,7 @@ public int hashCode() {
@Override
public String toString() {
StringWriter sw = new StringWriter();
try (JsonWriter jw = new JsonWriterImpl(sw, bufferPool)) {
try (JsonWriter jw = new JsonWriterImpl(sw, bufferPool, Collections.emptyMap())) {
jw.write(this);
}
return sw.toString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ public int hashCode() {
@Override
public String toString() {
StringWriter sw = new StringWriter();
try (JsonWriter jw = new JsonWriterImpl(sw, bufferPool)) {
try (JsonWriter jw = new JsonWriterImpl(sw, bufferPool, Collections.emptyMap())) {
jw.write(this);
}
return sw.toString();
Expand Down
21 changes: 17 additions & 4 deletions impl/src/main/java/org/eclipse/parsson/JsonProviderImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,18 @@ public JsonGeneratorFactory createGeneratorFactory(Map<String, ?> config) {
pool = bufferPool;
} else {
providerConfig = new HashMap<>();
prettyPrinting = JsonProviderImpl.isPrettyPrintingEnabled(config);
addKnowProperty(providerConfig, config, JsonGenerator.WRITE_NAN_AS_NULLS);
addKnowProperty(providerConfig, config, JsonGenerator.WRITE_NAN_AS_STRINGS);
if (prettyPrinting=JsonProviderImpl.isPrettyPrintingEnabled(config)) {
// ?? It is set to true even if the property was false
providerConfig.put(JsonGenerator.PRETTY_PRINTING, true);
}
pool = (BufferPool)config.get(BufferPool.class.getName());
if (pool != null) {
providerConfig.put(BufferPool.class.getName(), pool);
} else {
pool = bufferPool;
}
providerConfig.putAll(config);
providerConfig = Collections.unmodifiableMap(providerConfig);
}

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

@Override
public JsonWriter createWriter(Writer writer) {
return new JsonWriterImpl(writer, bufferPool);
return new JsonWriterImpl(writer, bufferPool, Collections.emptyMap());
}

@Override
public JsonWriter createWriter(OutputStream out) {
return new JsonWriterImpl(out, bufferPool);
return new JsonWriterImpl(out, bufferPool, Collections.emptyMap());
}

@Override
Expand All @@ -132,7 +136,10 @@ public JsonWriterFactory createWriterFactory(Map<String, ?> config) {
pool = bufferPool;
} else {
providerConfig = new HashMap<>();
addKnowProperty(providerConfig, config, JsonGenerator.WRITE_NAN_AS_NULLS);
addKnowProperty(providerConfig, config, JsonGenerator.WRITE_NAN_AS_STRINGS);
if (prettyPrinting=JsonProviderImpl.isPrettyPrintingEnabled(config)) {
// ?? It is set to true even if the property was false
providerConfig.put(JsonGenerator.PRETTY_PRINTING, true);
}
pool = (BufferPool)config.get(BufferPool.class.getName());
Expand Down Expand Up @@ -279,6 +286,12 @@ public JsonBuilderFactory createBuilderFactory(Map<String, ?> config) {
return new JsonBuilderFactoryImpl(pool, rejectDuplicateKeys);
}

private void addKnowProperty(Map<String, Object> providerConfig, Map<String, ?> config, String property) {
if (config.containsKey(property)) {
providerConfig.put(property, config.get(property));
}
}

static boolean isPrettyPrintingEnabled(Map<String, ?> config) {
return config.containsKey(JsonGenerator.PRETTY_PRINTING);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,17 @@ class JsonWriterFactoryImpl implements JsonWriterFactory {

@Override
public JsonWriter createWriter(Writer writer) {
return new JsonWriterImpl(writer, prettyPrinting, bufferPool);
return new JsonWriterImpl(writer, prettyPrinting, bufferPool, config);
}

@Override
public JsonWriter createWriter(OutputStream out) {
return new JsonWriterImpl(out, prettyPrinting, bufferPool);
return new JsonWriterImpl(out, prettyPrinting, bufferPool, config);
}

@Override
public JsonWriter createWriter(OutputStream out, Charset charset) {
return new JsonWriterImpl(out, charset, prettyPrinting, bufferPool);
return new JsonWriterImpl(out, charset, prettyPrinting, bufferPool, config);
}

@Override
Expand Down
25 changes: 12 additions & 13 deletions impl/src/main/java/org/eclipse/parsson/JsonWriterImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import java.io.Writer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.Map;

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

JsonWriterImpl(Writer writer, BufferPool bufferPool) {
this(writer, false, bufferPool);
JsonWriterImpl(Writer writer, BufferPool bufferPool, Map<String, ?> config) {
this(writer, false, bufferPool, config);
}

JsonWriterImpl(Writer writer, boolean prettyPrinting, BufferPool bufferPool) {
JsonWriterImpl(Writer writer, boolean prettyPrinting, BufferPool bufferPool, Map<String, ?> config) {
generator = prettyPrinting
? new JsonPrettyGeneratorImpl(writer, bufferPool, Collections.emptyMap())
: new JsonGeneratorImpl(writer, bufferPool, Collections.emptyMap());
? new JsonPrettyGeneratorImpl(writer, bufferPool, config)
: new JsonGeneratorImpl(writer, bufferPool, config);
os = null;
}

JsonWriterImpl(OutputStream out, BufferPool bufferPool) {
this(out, StandardCharsets.UTF_8, false, bufferPool);
JsonWriterImpl(OutputStream out, BufferPool bufferPool, Map<String, ?> config) {
this(out, StandardCharsets.UTF_8, false, bufferPool, config);
}

JsonWriterImpl(OutputStream out, boolean prettyPrinting, BufferPool bufferPool) {
this(out, StandardCharsets.UTF_8, prettyPrinting, bufferPool);
JsonWriterImpl(OutputStream out, boolean prettyPrinting, BufferPool bufferPool, Map<String, ?> config) {
this(out, StandardCharsets.UTF_8, prettyPrinting, bufferPool, config);
}

JsonWriterImpl(OutputStream out, Charset charset,
boolean prettyPrinting, BufferPool bufferPool) {
boolean prettyPrinting, BufferPool bufferPool, Map<String, ?> config) {
// Decorating the given stream, so that buffered contents can be
// written without actually flushing the stream.
this.os = new NoFlushOutputStream(out);
generator = prettyPrinting
? new JsonPrettyGeneratorImpl(os, charset, bufferPool, Collections.emptyMap())
: new JsonGeneratorImpl(os, charset, bufferPool, Collections.emptyMap());
? new JsonPrettyGeneratorImpl(os, charset, bufferPool, config)
: new JsonGeneratorImpl(os, charset, bufferPool, config);
}

@Override
Expand Down
104 changes: 102 additions & 2 deletions impl/src/test/java/org/eclipse/parsson/tests/JsonWriterTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,20 @@

package org.eclipse.parsson.tests;

import jakarta.json.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.StringWriter;

import java.util.HashMap;
import java.util.Map;

import jakarta.json.Json;
import jakarta.json.JsonArray;
import jakarta.json.JsonObject;
import jakarta.json.JsonValue;
import jakarta.json.JsonWriter;
import jakarta.json.JsonWriterFactory;
import jakarta.json.stream.JsonGenerator;
import jakarta.json.stream.JsonGeneratorFactory;
import junit.framework.TestCase;

/**
Expand Down Expand Up @@ -214,6 +223,97 @@ public void testClose() throws Exception {
assertTrue(baos.isClosed());
}

private String nameValueNanInfinity(JsonWriterFactory writerFactory) {
StringWriter writer = new StringWriter();
JsonWriter jsonWriter = writerFactory.createWriter(writer);
JsonObject jsonObject = Json.createObjectBuilder()
.add("val1", Double.NaN)
.add("val2", 1.0)
.add("val3", 0.0)
.add("val4", Double.POSITIVE_INFINITY)
.add("val5", Double.NEGATIVE_INFINITY)
.add("val6", Json.createValue(Double.NaN))
.add("val7", Json.createValue(1.0))
.add("val8", Json.createValue(0.0))
.add("val9", Json.createValue(Double.POSITIVE_INFINITY))
.add("val10", Json.createValue(Double.NEGATIVE_INFINITY)).build();
jsonWriter.writeObject(jsonObject);
jsonWriter.close();
return writer.toString();
}

private String jsonNumberNanInfinity(JsonWriterFactory writerFactory, double value) {
StringWriter writer = new StringWriter();
JsonWriter jsonWriter = writerFactory.createWriter(writer);
jsonWriter.write(Json.createValue(value));
jsonWriter.close();
return writer.toString();
}

public void testNanInfinityDefault() {
Map<String, Object> config = new HashMap<>();
JsonWriterFactory writerFactory = Json.createWriterFactory(config);
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));
assertEquals("0.0", jsonNumberNanInfinity(writerFactory, 0.0));
assertEquals("1.0", jsonNumberNanInfinity(writerFactory, 1.0));
assertEquals("null", jsonNumberNanInfinity(writerFactory, Double.NaN));
assertEquals("null", jsonNumberNanInfinity(writerFactory, Double.POSITIVE_INFINITY));
assertEquals("null", jsonNumberNanInfinity(writerFactory, Double.NEGATIVE_INFINITY));
}

public void testNanInfinityWriteNanAsNull() {
Map<String, Object> config = new HashMap<>();
config.put(JsonGenerator.WRITE_NAN_AS_NULLS, true);
JsonWriterFactory writerFactory = Json.createWriterFactory(config);
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));
assertEquals("0.0", jsonNumberNanInfinity(writerFactory, 0.0));
assertEquals("1.0", jsonNumberNanInfinity(writerFactory, 1.0));
assertEquals("null", jsonNumberNanInfinity(writerFactory, Double.NaN));
assertEquals("null", jsonNumberNanInfinity(writerFactory, Double.POSITIVE_INFINITY));
assertEquals("null", jsonNumberNanInfinity(writerFactory, Double.NEGATIVE_INFINITY));
}

public void testNanInfinityWriteNanAsString() {
Map<String, Object> config = new HashMap<>();
config.put(JsonGenerator.WRITE_NAN_AS_STRINGS, true);
JsonWriterFactory writerFactory = Json.createWriterFactory(config);
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));
assertEquals("0.0", jsonNumberNanInfinity(writerFactory, 0.0));
assertEquals("1.0", jsonNumberNanInfinity(writerFactory, 1.0));
assertEquals("\"NaN\"", jsonNumberNanInfinity(writerFactory, Double.NaN));
assertEquals("\"+Infinity\"", jsonNumberNanInfinity(writerFactory, Double.POSITIVE_INFINITY));
assertEquals("\"-Infinity\"", jsonNumberNanInfinity(writerFactory, Double.NEGATIVE_INFINITY));
}

public void testNanInfinityBothFalse() {
Map<String, Object> config = new HashMap<>();
config.put(JsonGenerator.WRITE_NAN_AS_STRINGS, false);
config.put(JsonGenerator.WRITE_NAN_AS_NULLS, false);
JsonWriterFactory writerFactory = Json.createWriterFactory(config);
try {
nameValueNanInfinity(writerFactory);
fail("Expected a failure");
} catch (NumberFormatException e) {}
try {
jsonNumberNanInfinity(writerFactory, Double.NaN);
fail("Expected a failure");
} catch (NumberFormatException e) {}
assertEquals("0.0", jsonNumberNanInfinity(writerFactory, 0.0));
assertEquals("1.0", jsonNumberNanInfinity(writerFactory, 1.0));
}

public void testNanInfinityBothTrue() {
Map<String, Object> config = new HashMap<>();
config.put(JsonGenerator.WRITE_NAN_AS_STRINGS, true);
config.put(JsonGenerator.WRITE_NAN_AS_NULLS, true);
JsonWriterFactory writerFactory = Json.createWriterFactory(config);
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));
assertEquals("0.0", jsonNumberNanInfinity(writerFactory, 0.0));
assertEquals("1.0", jsonNumberNanInfinity(writerFactory, 1.0));
assertEquals("null", jsonNumberNanInfinity(writerFactory, Double.NaN));
assertEquals("null", jsonNumberNanInfinity(writerFactory, Double.POSITIVE_INFINITY));
assertEquals("null", jsonNumberNanInfinity(writerFactory, Double.NEGATIVE_INFINITY));
}
private static final class MyByteStream extends ByteArrayOutputStream {
boolean closed;

Expand Down

0 comments on commit fd48e04

Please sign in to comment.