GithubHelp home page GithubHelp logo

sjson-new's People

Contributors

craffit avatar duhemm avatar dwijnand avatar eed3si9n avatar jtjeferreira avatar jvican avatar sethtisue avatar sirthias avatar wsargent avatar xuwei-k avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

sjson-new's Issues

Consider moving the :*: type alias to the toplevel

I've imported LList.:*: enough times already..

I think it would be an improvement if it was imported when importing sjsonnew._, either by moving (or duplicating :-/) the type alias in the root package object, or by renaming LCons to :*:.

Reconsider the name of the "project" method on AdditionalFormats

AdditionalFormats is mixed into BasicJsonProtocol (and from there into other implicit cakes).

This means that importing sjsonew.BasicJsonProtocol._ will make project ambiguous between sbt's (macro) method) and this method.

I found this in fixing scripted tests when switching from sbinary to sjsonnew.

Feel free to close if you consider this a non-issue.

support OffsetDateTime

As per conversation with Joda author, OffsetDateTime is the ISO-8601 compatible representation of datetime.

Tuple syntax on LList

It would be cool if tuple syntax were available on LList, such as instead of xs.tail.head you could call x._2. Note, like calling .tail.head is a compile error on an LList of size 1, so would ._2.

a field with empty Vector value gets omitted

steps

Make an object with a Vector field, serialize it to JSON.

problem

The field is omitted. For example, in the following example, "diagnostics": [] is missing.

JsonRpcNotificationMessage(2.0, textDocument/publishDiagnostics, {"uri":"file:/xxx/Hello.scala"})

The receiver of the message is not happy.

expectation

Empty fields are not omitted.

notes

This was an intentional design added in #6.
I think Option[A] can continue to elide.

Fix benchmark/CI setup

Here's a recent build of master: https://travis-ci.org/eed3si9n/sjson-new/builds/255776069

If you look carefully it goes from running the tests to checking binary compatibility with MiMa.

What's missing is running the benchmarks, as defined in .travis.yml:

  - sbt "so test" "so benchmark/jmh:run -i 10 -wi 3 -f1 -t1" "so mimaReportBinaryIssues"

If you run it locally it's more obvious:

> so benchmark/jmh:run -i 10 -wi 3 -f1 -t1
>

I think this is an interaction between the sbt/sbt#3353 regression and sbt-doge.

Reconsider the highly fragile Builder

It's way too simple to create or compose JsonFormat instances that end up throwing runtime errors.

Here's a sample when running sbt/sbt's "actions/all" scripted test:

[info] sjsonnew.SerializationException: Unexpected builder state: End
[info]     at sjsonnew.package$.serializationError(package.scala:19)
[info]     at sjsonnew.Builder.stateError(Builder.scala:184)
[info]     at sjsonnew.Builder.beginArray(Builder.scala:66)
[info]     at sbt.internal.util.HListFormat$$anon$2.write(HListFormat.scala:25)
[info]     at sbt.internal.util.HListFormat$$anon$2.write(HListFormat.scala:23)
[info]     at sbt.internal.util.HListFormat$$anon$2.write(HListFormat.scala:27)
[info]     at sbt.internal.util.HListFormat$$anon$2.write(HListFormat.scala:23)
[info]     at sjsonnew.SupportConverter$class.toJsonUnsafe(SupportConverter.scala:23)
[info]     at sjsonnew.support.scalajson.unsafe.Converter$.toJsonUnsafe(Converter.scala:7)
[info]     at sjsonnew.SupportConverter$$anonfun$toJson$1.apply(SupportConverter.scala:14)
[info]     at scala.util.Try$.apply(Try.scala:192)
[info]     at sjsonnew.SupportConverter$class.toJson(SupportConverter.scala:14)
[info]     at sjsonnew.support.scalajson.unsafe.Converter$.toJson(Converter.scala:7)
[info]     at sbt.internal.util.PlainOutput.write(Output.scala:15)
[info]     at sbt.internal.util.FileBasedStore$$anonfun$write$1.apply(CacheStore.scala:39)
[info]     at sbt.internal.util.FileBasedStore$$anonfun$write$1.apply(CacheStore.scala:39)
[info]     at sbt.io.Using.apply(Using.scala:23)
[info]     at sbt.internal.util.FileBasedStore.write(CacheStore.scala:39)
[info]     at sbt.internal.util.Tracked$CacheHelp.save(Tracked.scala:58)
[info]     at sbt.internal.util.Tracked$$anonfun$inputChanged$1.apply(Tracked.scala:52)
[info]     at sbt.Classpaths$.cachedUpdate(Defaults.scala:1669)
[info]     at sbt.Classpaths$$anonfun$updateTask$1.apply(Defaults.scala:1519)
[info]     at sbt.Classpaths$$anonfun$updateTask$1.apply(Defaults.scala:1471)

I've hit this general problem in different manifestation over the last few weeks switching sbt's modules to sjson-new.

I've never run into these kinds of runtime errors when defining custom JSON typeclass instances using play-json.

iso custom types example doesn't compile

Copied from the example for custom types in the README:

Welcome to Scala 2.12.3 (OpenJDK 64-Bit Server VM, Java 1.8.0_131).
Type in expressions for evaluation. Or try :help.

scala> import sjsonnew._, LList.:*:
import sjsonnew._
import LList.$colon$times$colon

scala> import BasicJsonProtocol._
import BasicJsonProtocol._

scala> case class Person(name: String, value: Int)
defined class Person

scala> implicit val personIso = LList.iso(
     |          { p: Person => ("name", p.name) :*: ("value", p.value) :*: LNil },
     |          { case (_, name) :*: (_, value) :*: LNil => Person(name, value) })
<console>:22: error: missing parameter type for expanded function
The argument types of an anonymous function must be fully known. (SLS 8.5)
Expected type was: ? => ?
                { case (_, name) :*: (_, value) :*: LNil => Person(name, value) })
                ^

I'm also wary of whether this is even useful at all - doesn't the builder in this case require the order of the JSON properties to be the order that appears in the LList? If that's so, it's not a compliant JSON converter, since compliant JSON converters should allow properties to appear in any order.

LList's purpose

LList proports itself as a "Heterogeneous list with labels", but if you look at the definition of LCons:

final case class LCons[A1: JsonFormat: ClassManifest, A2 <: LList: JsonFormat](
    name: String, head: A1, tail: A2
) extends LList {
  // ..
}

.. it's defined in terms of types for which there exist JsonFormat instances (and it captures them).

LList should either change its description, and possibly even its name, or it shouldn't capture JsonFormat instances.

JDK 9 support (Replace the use of JAXB)

steps

Try running sbt 1 on JDK 9.

problem

[error] (*:update) java.lang.NoClassDefFoundError: javax/xml/bind/DatatypeConverter

notes

#11 introduces dependency to JAXB, which is not part of the classpath on JDK 9. Figure out an alternative or add dependency to it.

Using mapFormat with non-primitives explodes

Adding this test-case to sjsonnew.support.spray.CollectionFormatsSpec, in "The mapFormat" should:

"round trip a Map[Person, Int]" in assertRoundTrip(Map(person -> 1))
  def assertRoundTrip[A: JsonWriter: JsonReader](x: A) = {
    val jValue: JsValue = Converter.toJsonUnsafe(x)
    val y: A = Converter.fromJsonUnsafe[A](jValue)
    x mustEqual y
  }

blows up with this:

[error]   ! round trip a Map[Person, Int]
[error]    sjsonnew.SerializationException: Unexpected builder state: InObject (package.scala:19)
[error] sjsonnew.package$.serializationError(package.scala:19)
[error] sjsonnew.Builder.stateError(Builder.scala:184)
[error] sjsonnew.Builder.beginObject(Builder.scala:111)
[error] sjsonnew.support.spray.CollectionFormatsSpec$PersonFormat$.write(CollectionFormatsSpec.scala:30)
[error] sjsonnew.support.spray.CollectionFormatsSpec$PersonFormat$.write(CollectionFormatsSpec.scala:28)
[error] sjsonnew.CollectionFormats$$anon$3$$anonfun$write$3.apply(CollectionFormats.scala:96)
[error] sjsonnew.CollectionFormats$$anon$3$$anonfun$write$3.apply(CollectionFormats.scala:94)
[error] sjsonnew.CollectionFormats$$anon$3.write(CollectionFormats.scala:94)
[error] sjsonnew.CollectionFormats$$anon$3.write(CollectionFormats.scala:88)
[error] sjsonnew.SupportConverter$class.toJsonUnsafe(SupportConverter.scala:23)
[error] sjsonnew.support.spray.Converter$.toJsonUnsafe(Converter.scala:6)
[error] sjsonnew.support.spray.CollectionFormatsSpec.assertRoundTrip(CollectionFormatsSpec.scala:119)
[error] sjsonnew.support.spray.CollectionFormatsSpec$$anonfun$3$$anonfun$apply$22.apply(CollectionFormatsSpec.scala:90)
[error] sjsonnew.support.spray.CollectionFormatsSpec$$anonfun$3$$anonfun$apply$22.apply(CollectionFormatsSpec.scala:90)

LListOps does not work with Scala 3

because Scala 3 generate _1, _2 methods for case classes. LCons is case class ๐Ÿ˜‡

  • final class LListOps[L <: LList](l: L) {
    import Nat._
    def _1(implicit at: At[L, _0]): at.Out = at(l)
    def _2(implicit at: At[L, _1]): at.Out = at(l)
    def _3(implicit at: At[L, _2]): at.Out = at(l)
    def _4(implicit at: At[L, _3]): at.Out = at(l)
    def _5(implicit at: At[L, _4]): at.Out = at(l)
    def _6(implicit at: At[L, _5]): at.Out = at(l)
    def _7(implicit at: At[L, _6]): at.Out = at(l)
    def _8(implicit at: At[L, _7]): at.Out = at(l)
    def _9(implicit at: At[L, _8]): at.Out = at(l)
    def _10(implicit at: At[L, _9]): at.Out = at(l)
    def _11(implicit at: At[L, _10]): at.Out = at(l)
    def _12(implicit at: At[L, _11]): at.Out = at(l)
    def _13(implicit at: At[L, _12]): at.Out = at(l)
    def _14(implicit at: At[L, _13]): at.Out = at(l)
    def _15(implicit at: At[L, _14]): at.Out = at(l)
    def _16(implicit at: At[L, _15]): at.Out = at(l)
    def _17(implicit at: At[L, _16]): at.Out = at(l)
    def _18(implicit at: At[L, _17]): at.Out = at(l)
    def _19(implicit at: At[L, _18]): at.Out = at(l)
    def _20(implicit at: At[L, _19]): at.Out = at(l)
    def _21(implicit at: At[L, _20]): at.Out = at(l)
    def _22(implicit at: At[L, _21]): at.Out = at(l)
    }
  • final case class LCons[A1: JsonFormat: ClassTag, A2 <: LList: JsonFormat](name: String, head: A1, tail: A2) extends LList {
Welcome to Scala 3.1.1-RC1 (1.8.0_312, Java OpenJDK 64-Bit Server VM).
Type in expressions for evaluation. Or try :help.
                                                                                                                                                                                                 
scala> case class A(x1: Int, x2: String)
val a // defined case class A
                                                                                                                                                                                                 
scala> val a = A(2, "b")
val a: A = A(2,b)
                                                                                                                                                                                                 
scala> a._1
val res0: Int = 2
                                                                                                                                                                                                 
scala> a._2
val res1: String = b
                                                                                                                                                                                                 
scala> a._3
-- [E008] Not Found Error: -----------------------------------------------------
1 |a._3
  |^^^^
  |value _3 is not a member of A
1 error found
                                                                                                                                                                                                 
scala> implicit class AOps(self: A) { def _1 = "AOps._1" }
// defined class AOps
def AOps(self: A): AOps
                                                                                                                                                                                                 
scala> a._1
val res2: Int = 2
  • add another name methods to LListOps?
  • avoid case class?
-final case class LCons[A1: JsonFormat: ClassTag, A2 <: LList: JsonFormat](name: String, head: A1, tail: A2) extends LList {
+final class LCons[A1: JsonFormat: ClassTag, A2 <: LList: JsonFormat](val name: String, val head: A1, val tail: A2) extends LList with Product with Serializable with Equals {
+  override def canEqual(that: Any): Boolean = that.isInstanceOf[LCons[_, _]]
+  override def productArity: Int = 3
+  override def productElement(n: Int): Any = n match {
+    case 0 => name
+    case 1 => head
+    case 2 => tail
+    case _ => throw new IndexOutOfBoundsException(Integer.toString(n))
+  }
+  def copy[B1: JsonFormat: ClassTag, B2 <: LList: JsonFormat](name: String = name, head: B1 = head, tail: B2 = tail): LCons[B1, B2] =
+    new LCons[B1, B2](name, head, tail)
+
+  override def hashCode(): Int = scala.runtime.ScalaRunTime._hashCode(this)
+
+  override def equals(x$1: Any): Boolean = x$1 match {
+    case that: LCons[_, _] =>
+      (this.name == that.name) && (this.head == that.head) && (this.tail == that.tail)
+    case _ =>
+      false
+  }
+
   def :*:[B1: JsonFormat: ClassTag](labelled: (String, B1)): B1 :*: A1 :*: A2 = LCons(labelled._1, labelled._2, this)
   override def toString: String = s"($name, $head) :*: $tail"
+  override def productPrefix: String = "LCons"
   override def find[B1: ClassTag](n: String): Option[B1] =
     if (name == n && implicitly[ClassTag[A1]] == implicitly[ClassTag[B1]]) Option(head match { case x: B1 @unchecked => x })
     else tail.find[B1](n)
   override def fieldNames: List[String] = name :: tail.fieldNames
 }
 
+object LCons extends Serializable {
+  override def toString: String = "LCons"
+  def apply[A1: JsonFormat: ClassTag, A2 <: LList: JsonFormat](name: String, head: A1, tail: A2): LCons[A1, A2] =
+    new LCons[A1, A2](name = name, head = head, tail = tail)
+  def unapply[A1, A2 <: LList](x$0: LCons[A1, A2]): Option[(String, A1, A2)] =
+    if (x$0 == null) {
+      None
+    } else {
+      Some((x$0.name, x$0.head, x$0.tail))
+    }
+}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.