circe-yaml icon indicating copy to clipboard operation
circe-yaml copied to clipboard

Float / Double serialized in unnatural way

Open OndrejSpanel opened this issue 5 years ago • 3 comments

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

OndrejSpanel avatar May 24 '19 18:05 OndrejSpanel

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

OndrejSpanel avatar May 28 '19 14:05 OndrejSpanel

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.

OndrejSpanel avatar May 29 '19 20:05 OndrejSpanel

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.

OndrejSpanel avatar May 30 '19 09:05 OndrejSpanel