Skip to content

Commit 86811ef

Browse files
committed
provide NaN and Infinity for reading
Signed-off-by: Jorge Bescos Gascon <[email protected]>
1 parent fd48e04 commit 86811ef

File tree

5 files changed

+112
-16
lines changed

5 files changed

+112
-16
lines changed

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -192,8 +192,8 @@ public JsonGenerator write(String name, double value) {
192192
throw new JsonGenerationException(
193193
JsonMessages.GENERATOR_ILLEGAL_METHOD(currentContext.scope));
194194
}
195-
NaNInfinite normalNaNInfinite = NaNInfinite.get(value);
196-
Object result = normalNaNInfinite == null ? value : normalNaNInfinite.processValue(writeNanAsNulls, writeNanAsStrings, value);
195+
NaNInfinite nanInfinite = NaNInfinite.get(value);
196+
Object result = nanInfinite == null ? value : nanInfinite.processValue(writeNanAsNulls, writeNanAsStrings, value);
197197
writeName(name);
198198
writeString(String.valueOf(result));
199199
return this;
@@ -409,11 +409,11 @@ public JsonGenerator write(long value) {
409409
@Override
410410
public JsonGenerator write(double value) {
411411
checkContextForValue();
412-
NaNInfinite normalNaNInfinite = NaNInfinite.get(value);
413-
if (normalNaNInfinite == null) {
412+
NaNInfinite nanInfinite = NaNInfinite.get(value);
413+
if (nanInfinite == null) {
414414
writeValue(String.valueOf(value));
415415
} else {
416-
Object result = normalNaNInfinite.processValue(writeNanAsNulls, writeNanAsStrings, value);
416+
Object result = nanInfinite.processValue(writeNanAsNulls, writeNanAsStrings, value);
417417
writeValue(String.valueOf(result));
418418
}
419419
popFieldContext();

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

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,20 +45,42 @@ static JsonNumber getJsonNumber(BigInteger value) {
4545
}
4646

4747
static JsonNumber getJsonNumber(double value) {
48-
NaNInfinite normalNaNInfinite = NaNInfinite.get(value);
49-
if (normalNaNInfinite == null) {
48+
NaNInfinite nanInfinite = NaNInfinite.get(value);
49+
if (nanInfinite == null) {
5050
//bigDecimal = new BigDecimal(value);
5151
// This is the preferred way to convert double to BigDecimal
5252
return new JsonBigDecimalNumber(BigDecimal.valueOf(value));
5353
} else {
54-
return new JsonNaNInfiniteNumber(value, normalNaNInfinite);
54+
return JsonNaNInfiniteNumber.get(nanInfinite);
5555
}
5656
}
5757

5858
static JsonNumber getJsonNumber(BigDecimal value) {
5959
return new JsonBigDecimalNumber(value);
6060
}
6161

62+
static final class JsonNullNumber extends JsonNumberImpl {
63+
64+
static final JsonNullNumber NULL = new JsonNullNumber();
65+
66+
private JsonNullNumber() {}
67+
68+
@Override
69+
public Number numberValue() {
70+
return null;
71+
}
72+
73+
@Override
74+
public boolean isIntegral() {
75+
return false;
76+
}
77+
78+
@Override
79+
public BigDecimal bigDecimalValue() {
80+
throw new NullPointerException("Value is null");
81+
}
82+
}
83+
6284
// Optimized JsonNumber impl for int numbers.
6385
private static final class JsonIntNumber extends JsonNumberImpl {
6486
private final int num;
@@ -184,6 +206,9 @@ public String toString() {
184206

185207
static final class JsonNaNInfiniteNumber extends JsonNumberImpl {
186208

209+
private static final JsonNaNInfiniteNumber NAN = new JsonNaNInfiniteNumber(Double.NaN, NaNInfinite.NAN);
210+
private static final JsonNaNInfiniteNumber POSITIVE_INFINITY = new JsonNaNInfiniteNumber(Double.POSITIVE_INFINITY, NaNInfinite.POSITIVE_INFINITY);
211+
private static final JsonNaNInfiniteNumber NEGATIVE_INFINITY = new JsonNaNInfiniteNumber(Double.NEGATIVE_INFINITY, NaNInfinite.NEGATIVE_INFINITY);
187212
private final double num;
188213
private final NaNInfinite naNInfinite;
189214

@@ -196,16 +221,38 @@ NaNInfinite naNInfinite() {
196221
return naNInfinite;
197222
}
198223

224+
@Override
225+
public boolean isIntegral() {
226+
return false;
227+
}
228+
199229
@Override
200230
public double doubleValue() {
201231
return num;
202232
}
203233

234+
@Override
235+
public Number numberValue() {
236+
return num;
237+
}
238+
204239
@Override
205240
public BigDecimal bigDecimalValue() {
206241
// Every other method in this class that is not overridden will fail because of this exception
207242
throw new UnsupportedOperationException("Value is " + num);
208243
}
244+
245+
static JsonNaNInfiniteNumber get(NaNInfinite nanInfinite) {
246+
if (nanInfinite == NaNInfinite.NAN) {
247+
return NAN;
248+
} else if (nanInfinite == NaNInfinite.NEGATIVE_INFINITY) {
249+
return NEGATIVE_INFINITY;
250+
} else if (nanInfinite == NaNInfinite.POSITIVE_INFINITY) {
251+
return POSITIVE_INFINITY;
252+
} else {
253+
throw new IllegalArgumentException(nanInfinite + " is not known");
254+
}
255+
}
209256
}
210257

211258
// JsonNumber impl using BigDecimal numbers.

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

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,29 @@
1616

1717
package org.eclipse.parsson;
1818

19-
import org.eclipse.parsson.api.BufferPool;
20-
21-
import jakarta.json.*;
2219
import java.io.StringWriter;
2320
import java.math.BigDecimal;
2421
import java.math.BigInteger;
25-
import java.util.*;
22+
import java.util.AbstractMap;
23+
import java.util.Collections;
24+
import java.util.LinkedHashMap;
25+
import java.util.Map;
26+
import java.util.Optional;
27+
import java.util.Set;
28+
29+
import org.eclipse.parsson.JsonNumberImpl.JsonNaNInfiniteNumber;
30+
import org.eclipse.parsson.JsonNumberImpl.JsonNullNumber;
31+
import org.eclipse.parsson.JsonUtil.NaNInfinite;
32+
import org.eclipse.parsson.api.BufferPool;
33+
34+
import jakarta.json.JsonArray;
35+
import jakarta.json.JsonArrayBuilder;
36+
import jakarta.json.JsonNumber;
37+
import jakarta.json.JsonObject;
38+
import jakarta.json.JsonObjectBuilder;
39+
import jakarta.json.JsonString;
40+
import jakarta.json.JsonValue;
41+
import jakarta.json.JsonWriter;
2642

2743
/**
2844
* JsonObjectBuilder implementation
@@ -246,7 +262,17 @@ public JsonObject getJsonObject(String name) {
246262

247263
@Override
248264
public JsonNumber getJsonNumber(String name) {
249-
return (JsonNumber)get(name);
265+
JsonValue value = get(name);
266+
if (value.getValueType() == ValueType.NULL) {
267+
return JsonNullNumber.NULL;
268+
} else {
269+
NaNInfinite nanInfinite = null;
270+
if (value.getValueType() == ValueType.STRING && (nanInfinite = NaNInfinite.get(value.toString())) != null) {
271+
return JsonNaNInfiniteNumber.get(nanInfinite);
272+
} else {
273+
return (JsonNumber)get(name);
274+
}
275+
}
250276
}
251277

252278
@Override

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,15 @@ static NaNInfinite get(double value) {
122122
return null;
123123
}
124124
}
125+
126+
static NaNInfinite get(String value) {
127+
for (NaNInfinite item : NaNInfinite.values()) {
128+
if (item.strVal.equals(value)) {
129+
return item;
130+
}
131+
}
132+
return null;
133+
}
125134
}
126135
}
127136

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

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,15 @@
2323
import java.util.HashMap;
2424
import java.util.Map;
2525

26+
import org.eclipse.parsson.api.BufferPool;
27+
2628
import jakarta.json.Json;
2729
import jakarta.json.JsonArray;
2830
import jakarta.json.JsonNumber;
2931
import jakarta.json.JsonObject;
3032
import jakarta.json.JsonReader;
3133
import jakarta.json.JsonReaderFactory;
3234
import jakarta.json.JsonValue;
33-
34-
import org.eclipse.parsson.api.BufferPool;
35-
3635
import junit.framework.TestCase;
3736

3837
/**
@@ -204,4 +203,19 @@ public void testEmptyStringUsingBuffers() throws Throwable {
204203
}
205204
}
206205

206+
public void testNanInfinity() {
207+
// Configuration is irrelevant for reading, it just understands how to parse it.
208+
Map<String, Object> config = new HashMap<>();
209+
JsonReaderFactory factory = Json.createReaderFactory(config);
210+
String json = "{\"val1\":null,\"val2\":1.0,\"val3\":0.0,\"val4\":\"NaN\",\"val5\":\"+Infinity\",\"val6\":\"-Infinity\"}";
211+
JsonReader reader = factory.createReader(new StringReader(json));
212+
JsonObject object = reader.readObject();
213+
reader.close();
214+
assertEquals(null, object.getJsonNumber("val1").numberValue());
215+
assertEquals(1.0, object.getJsonNumber("val2").doubleValue());
216+
assertEquals(0.0, object.getJsonNumber("val3").doubleValue());
217+
assertTrue(Double.isNaN(object.getJsonNumber("val4").doubleValue()));
218+
assertEquals(Double.POSITIVE_INFINITY, object.getJsonNumber("val5").doubleValue());
219+
assertEquals(Double.NEGATIVE_INFINITY, object.getJsonNumber("val6").doubleValue());
220+
}
207221
}

0 commit comments

Comments
 (0)