circe-yaml
circe-yaml copied to clipboard
Float / Double serialized in unnatural way
Fractional double values are printed in a quite unexpected way. This is what I get:
points:
- x: -0
y: 1
- x: -5519150495529175e-16
y: 1
- x: -1
y: 5519150495529175e-16
- x: -1
y: 0
While not incorrect, this is quite unexpected and not much human readable. This is what I would like to get:
points:
- x: -0
y: 1
- x: -0.5519150495529175
y: 1
- x: -1
y: 0.55519150495529175
- x: -1
y: 0
A similar issue can be seen with doubles which are integer values:
y: !!int '1.0E8'
or
y: !!int '1000.0'
I would like to see:
y: 1.0E8
y: 1000.0
or
y: 100000000.0
y: 1000.0
or
y: 100000000
y: 1000
I have a repro for this one:
import io.circe._
import io.circe.syntax._
import io.circe.generic.auto._
object Main extends App {
case class Data(x: Double, y: Double)
val foo = Seq(
Data(0.0000001, 100000000),
Data(0.1234567891234569, 1000)
)
val json = foo.asJson
val printer = yaml.Printer.spaces2
val yamlString = printer.pretty(json)
println(yamlString)
}
Note: cross posted on Stack Overflow
I am unable to reproduce the first issue in a small repro so far.
I have prepared a commit for the second issue - once the node is tagged as INT, integer format is also used for the number, therefore the tag will not be emitted (it is emitted only when the natural number string interpretation does not match the tag).
Hopefully this could become a PR sometimes soon. If anyone can review or comment, I will be glad.
I have a repro for the issue, the cause seems to lie in the parser, not in the printer:
val input =
"""
|---
|x: 0.12345678901234567
""".stripMargin
import io.circe.yaml.parser._
val json = parse(input).right.get
val output = printer.pretty(json)
assert(!(output contains "!!")) // no type tags expected in the output
assert(!(output contains "e-")) // scientific notation not expected in the output
The output is x: 12345678901234567e-17
.
The cause of this is that while parsing x: 0.12345678901234567
the value is represented as JsonBiggerDecimal
with a value of 12345678901234567e-17
. For comparison, the Circe parses a similar JSON input {"x": 0.12345678901234567}
differently, the value is parsed as JsonDecimal
with a value of 0.12345678901234567
.