mdedetrich / scalajson

ScalaJSON - JSON for Scala, currently contains minimal AST
BSD 3-Clause "New" or "Revised" License
55 stars 10 forks source link
ast json scala

ScalaJSON

Join the chat at https://gitter.im/mdedetrich/scalajson codecov.io Build Status Scala.js

ScalaJSON library, currently provides two minimal implementations of JSON AST, one that is designed for typical use and another that is designed for performance/corner cases.

Usage

Built for Scala 2.10.x, 2.11.x, 2.12.x, and 2.13.x milestones.

"org.scala-lang.platform" %% "scalajson" % "1.0.0-M4"

If you are using Scala.js, you need to do

"org.scala-lang.platform" %%% "scalajson" % "1.0.0-M4"

Standard AST

Implementation is in scalajson.ast.JValue

Goals

Unsafe AST

Implementation is in scalajson.unsafe.JValue

Goals

Conversion between scalajson.JValue and scalajson.ast.unsafe.JValue

Any scalajson.ast.JValue implements a conversion to scalajson.ast.unsafe.JValue with a toUnsafe method and vice versa with a toStandard method. These conversion methods have been written to be as fast as possible.

There are some peculiarities when converting between the two AST's. When converting a scalajson.ast.unsafe.JNumber to a scalajson.ast.JNumber, it is possible for this to fail at runtime (since the internal representation of scalajson.ast.unsafe.JNumber is a String and it doesn't have a runtime check). It is up to the caller on how to handle this error (and when), a runtime check is deliberately avoided on our end for performance reasons.

Converting from a scalajson.ast.JObject to a scalajson.ast.unsafe.JObject will produce an scalajson.ast.unsafe.JObject with an undefined ordering for its internal Array/js.Array representation. This is because a Map has no predefined ordering. If you wish to provide ordering, you will either need to write your own custom conversion to handle this case. Duplicate keys will also be removed for the same reason in an undefined manner.

Do note that according to the JSON spec, whether to order keys for a JObject is not specified. Also note that Map disregards ordering for equality, however Array/js.Array equality takes ordering into account.

Number conversions

ScalaJSON JNumber provides conversions to various number types with the following conventions

With the .toFloat and .toDouble methods, if you don't want any loss in precision, its advisable to convert to BigDecimal first and then work from there, i.e. when working with Decimal/Float, its implied that you will have loss of precision.

Remember that in all cases if these methods are not applicable, you can always use the .value field to get the original string representation of the number.

Scala.js

ScalaJSON also provides support for Scala.js. The usage of Scala.js mirrors the usage of Scala on the JVM however Scala.js also implements a .toJsAny method which allows you to convert any scalajson.ast.JValue/scalajson.ast.unsafe.JValue to a Javascript value in Scala.js.

Note that, since a scalajson.ast.JNumber/scalajson.ast.unsafe.JNumber is unlimited precision (represented internally as a String), calls to .toJsAny can lose precision on the underlying number (numbers in Javascript are represented as double precision floating point number). You can use the .value method on a scalajson.ast.JNumber/scalajson.ast.unsafe.JNumber to get the raw string value as a solution to this problem.

Further, toFloat on JNumber (see Number Conversions ) can have different semantics on Scala.js, depending on whether you have strict-floats enabled in your application. Please see the Scala.js semantics page for more information.

jNumberRegex

scalajson.JNumber uses jNumberRegex to validate whether a number is a valid JSON number. One can use jNumberRegex explicitly if you want to use the validation that is used by scalajson.JNumber (for example, you may want to validate proper numbers before creating a scalajson.unsafe.JNumber).

import scalajson.jNumberRegex

"3535353" match {
  case jNumberRegex(_ *) => true
  case _ => false
}

Code of Conduct

ScalaJSON uses the Scala Code of Conduct for all communication and discussion. This includes both GitHub, Gitter chat and other more direct lines of communication such as email.

Code formatting

The project is formatted using scalafmt. Please run scalafmt in SBT before committing any changes