Skip to content

Commit 0be3cea

Browse files
serialize xs:double/xs:float negative zero as '-0' (#2639)
1 parent 622d4d0 commit 0be3cea

File tree

8 files changed

+26
-5
lines changed

8 files changed

+26
-5
lines changed

basex-core/src/main/java/org/basex/io/serial/json/JsonSerializer.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,8 @@ protected void atomic(final Item item) throws IOException {
178178
if(type.oneOf(BasicType.DOUBLE, BasicType.FLOAT) || canonical && type.isNumber()) {
179179
final double d = item.dbl(null);
180180
if(Double.isFinite(d)) {
181-
out.print(Dbl.string(d));
181+
final byte[] s = Dbl.string(d);
182+
out.print(canonical && s == NEGATIVE_ZERO ? token(0) : s);
182183
} else {
183184
if(canonical) throw SERNUMBER_X.getIO(d);
184185
out.print(d == Double.POSITIVE_INFINITY ? JsonConstants.INF :

basex-core/src/main/java/org/basex/query/value/item/Dbl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ public static double parse(final byte[] value, final InputInfo info) throws Quer
168168
*/
169169
public static byte[] string(final double value) {
170170
// handle known edge cases
171-
if(value == 0) return Token.token(0);
171+
if(value == 0) return 1 / value > 0 ? Token.token(0) : Token.NEGATIVE_ZERO;
172172
if(value == Double.MIN_VALUE) return Token.token("5e-324");
173173
if(value == -Double.MIN_VALUE) return Token.token("-5e-324");
174174
if(value == 1e23) return Token.token("1e+23");

basex-core/src/test/java/org/basex/io/serial/json/BaseXSerializerTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ public final class BaseXSerializerTest extends SandboxTest {
2222
serialize("()", "");
2323
serialize("1", "1");
2424
serialize("1, 2", "1\n2");
25+
serialize("xs:double('-0'), xs:float('-0')", "-0\n-0");
2526

2627
// nodes
2728
serialize("<x/>", "<x/>");

basex-core/src/test/java/org/basex/io/serial/json/JsonSerializerTest.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ public final class JsonSerializerTest extends SandboxTest {
2727
final JsonFormat format = JsonFormat.DIRECT;
2828
serialize("'x'", "'x'", format);
2929
serialize("1", "1", format);
30+
serialize("xs:double('-0')", "-0", format);
31+
serialize("xs:float('-0')", "-0", format);
3032
serialize("true()", "true", format);
3133
serialize("<_/>", "'<_\\/>'", format);
3234

@@ -64,6 +66,8 @@ public final class JsonSerializerTest extends SandboxTest {
6466
final JsonFormat format = JsonFormat.ATTRIBUTES;
6567
serialize("'x'", "'x'", format);
6668
serialize("1", "1", format);
69+
serialize("xs:double('-0')", "-0", format);
70+
serialize("xs:float('-0')", "-0", format);
6771
serialize("true()", "true", format);
6872
serialize("<_/>", "'<_\\/>'", format);
6973

@@ -116,6 +120,8 @@ public final class JsonSerializerTest extends SandboxTest {
116120
serialize("{ 'A': false() }", "{'A':false}", format);
117121
serialize("{ true(): false() }", "{'true':false}", format);
118122
serialize("{ 1: 'E' }", "{'1':'E'}", format);
123+
serialize("{ 0: xs:double('-0') }", "{'0':-0}", format);
124+
serialize("{ 0: xs:float('-0') }", "{'0':-0}", format);
119125

120126
serialize("{ 'A': 1 div 0.0e0 }", "{'A':1e9999}", format);
121127
serialize("{ 'A': -1 div 0.0e0 }", "{'A':-1e9999}", format);
@@ -129,6 +135,8 @@ public final class JsonSerializerTest extends SandboxTest {
129135
serialize("[ 2 ]", "[2]", format);
130136
serialize("[ 2, 3 ]", "[2,3]", format);
131137
serialize("[ 2, (), 4 ]", "[2,null,4]", format);
138+
serialize("[ xs:double('-0') ]", "[-0]", format);
139+
serialize("[ xs:float('-0') ]", "[-0]", format);
132140

133141
error("[ (1, 2) ]", format, SERJSONSEQ);
134142

@@ -146,7 +154,8 @@ public final class JsonSerializerTest extends SandboxTest {
146154
serialize("1", "1", format);
147155

148156
serialize("0.0e0", "0", format);
149-
serialize("-0.0e0", "0", format);
157+
serialize("-0.0e0", "-0", format);
158+
serialize("xs:float('-0')", "-0", format);
150159
serialize("1e-6", "0.000001", format);
151160
serialize("1e-7", "1e-7", format);
152161
serialize("1e20", "100000000000000000000", format);

basex-core/src/test/java/org/basex/query/SerializerTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ public final class SerializerTest extends SandboxTest {
262262
query(option + "1234567890e0", "1.23456789e9");
263263
query(option + "xs:double('NaN')", "NaN");
264264
query(option + "xs:double('INF')", "INF");
265+
query(option + "xs:double('-0')", "-0.0e0");
265266
query(option + "xs:byte(1)", 1);
266267
query(option + "false()", "false()");
267268
query(option + "'A'", "\"A\"");
@@ -273,6 +274,7 @@ public final class SerializerTest extends SandboxTest {
273274
query(option + "true#0", "fn:true#0");
274275
query(option + "fn() {}", "fn() as empty-sequence() { () }");
275276
query(option + "xs:float(1)", "xs:float(\"1\")");
277+
query(option + "xs:float('-0')", "xs:float(\"-0\")");
276278

277279
query(option + "[]", "[]");
278280
query(option + "[ 1 ]", "[1]");
@@ -281,6 +283,7 @@ public final class SerializerTest extends SandboxTest {
281283
query(option + "[ 1234567890e0 ]", "[1.23456789e9]");
282284
query(option + "[ xs:double('NaN') ]", "[NaN]");
283285
query(option + "[ xs:double('INF') ]", "[INF]");
286+
query(option + "[ xs:double('-0') ]", "[-0.0e0]");
284287
query(option + "[ xs:byte(1) ]", "[1]");
285288
query(option + "[ false() ]", "[false()]");
286289
query(option + "[ 'A' ]", "[\"A\"]");
@@ -292,6 +295,7 @@ public final class SerializerTest extends SandboxTest {
292295
query(option + "[ true#0 ]", "[fn:true#0]");
293296
query(option + "[ fn() {} ]", "[fn() as empty-sequence() { () }]");
294297
query(option + "[ xs:float(1) ]", "[xs:float(\"1\")]");
298+
query(option + "[ xs:float('-0')]", "[xs:float(\"-0\")]");
295299

296300
query(option + "{ 1: (), 2: 3, 4: (5, 6) }", "{1:(),2:3,4:(5,6)}");
297301
}
@@ -305,6 +309,7 @@ public final class SerializerTest extends SandboxTest {
305309
query("1234567890e0", 1234567890);
306310
query("xs:double('NaN')", "NaN");
307311
query("xs:double('INF')", "INF");
312+
query("xs:double('-0')", "-0");
308313
query("xs:byte(1)", 1);
309314
query("false()", "false");
310315
query("'A'", "A");
@@ -316,6 +321,7 @@ public final class SerializerTest extends SandboxTest {
316321
query("true#0", "fn:true#0");
317322
query("fn() {}", "fn() as empty-sequence() { () }");
318323
query("xs:float(1)", 1);
324+
query("xs:float('-0')", "-0");
319325

320326
query("[]", "[]");
321327
query("[ 1 ]", "[1]");

basex-core/src/test/java/org/basex/query/func/BinModuleTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,7 @@ public final class BinModuleTest extends SandboxTest {
410410
query(func.args(hex("0000000000000000"), 0), 0);
411411
query(func.args(hex("3FF0000000000000"), 0), 1);
412412
query(func.args(hex("BFF0000000000000"), 0), -1);
413-
query(func.args(hex("8000000000000000"), 0), 0);
413+
query(func.args(hex("8000000000000000"), 0), "-0");
414414
query(func.args(hex("0000000000000000"), 0), 0);
415415
query(func.args(hex("7FF0000000000000"), 0), "INF");
416416
query(func.args(hex("FFF0000000000000"), 0), "-INF");

basex-core/src/test/java/org/basex/query/func/FnModuleTest.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3189,6 +3189,8 @@ public final class FnModuleTest extends SandboxTest {
31893189

31903190
final String canonicalJson = " {'method': 'json', 'canonical': true()}";
31913191
query(func.args(" [0x7fff_ffff_ffff_ffff]", canonicalJson), "[9223372036854776000]");
3192+
query(func.args(" [xs:double('-0')]", " {'method': 'json'}"), "[-0]");
3193+
query(func.args(" [xs:double('-0')]", canonicalJson), "[0]");
31923194

31933195
// The tests below were adapted from Apache 2.0–licensed code from project
31943196
// erdtman/java-json-canonicalization at https://github.com/erdtman/java-json-canonicalization
@@ -3436,6 +3438,8 @@ public final class FnModuleTest extends SandboxTest {
34363438
query(func.args("A"), "A");
34373439
query(func.args(wrap("A")), "A");
34383440
query("(" + wrap("A") + ", 1, 'X') ! " + func.args(), "A\n1\nX");
3441+
query(func.args(" xs:float('-0')"), "-0");
3442+
query(func.args(" xs:double('-0')"), "-0");
34393443

34403444
check("for $s in ('a', 'b') return " + func.args(" $s"), "a\nb", empty(func));
34413445
check("for $s in (<a/>, <b/>) return " + func.args(" $s"), "\n", exists(func));

basex-core/src/test/java/org/basex/query/func/JsonModuleTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ public final class JsonModuleTest extends SandboxTest {
120120
query(func.args("0E1", options), 0);
121121
query(func.args("0E-1", options), 0);
122122
query(func.args("0E+1", options), 0);
123-
query(func.args("-0E+1", options), "0");
123+
query(func.args("-0E+1", options), "-0");
124124
query(func.args("0E00", options), 0);
125125
query(func.args("123e-123", options), "1.23e-121");
126126
query(func.args("123.4e-123", options), "1.234e-121");

0 commit comments

Comments
 (0)