标签: argonaut

将类型与数据构造函数关联的ADT编码有什么问题?(比如Scala.)

在Scala中,代数数据类型被编码为sealed一级类型层次结构.例:

-- Haskell
data Positioning a = Append
                   | AppendIf (a -> Bool)
                   | Explicit ([a] -> [a]) 
Run Code Online (Sandbox Code Playgroud)
// Scala
sealed trait Positioning[A]
case object Append extends Positioning[Nothing]
case class AppendIf[A](condition: A => Boolean) extends Positioning[A]
case class Explicit[A](f: Seq[A] => Seq[A]) extends Positioning[A]
Run Code Online (Sandbox Code Playgroud)

随着case classES和case objectS,斯卡拉产生了一堆东西一样equals,hashCode,unapply(通过模式匹配使用)等这使我们的许多关键特性和传统的ADT功能.

但是有一个关键的区别 - 在Scala中,"数据构造函数"有自己的类型.比较以下两个例子(从相应的REPL复制).

// Scala

scala> :t Append
Append.type

scala> :t AppendIf[Int](Function const true)
AppendIf[Int]

-- Haskell

haskell> :t Append …
Run Code Online (Sandbox Code Playgroud)

haskell functional-programming scala playframework argonaut

68
推荐指数
1
解决办法
2311
查看次数

找不到隐式ExecutionContext.你可能会通过喷雾scala

我有这两个错误:

Error:(39, 20) Cannot find an implicit ExecutionContext. You might pass
an (implicit ec: ExecutionContext) parameter to your method
or import scala.concurrent.ExecutionContext.Implicits.global.
    val pipeline = sendReceive

               ^

Error:(39, 20) not enough arguments for method sendReceive: (implicit refFactory: akka.actor.ActorRefFactory, implicit executionContext: scala.concurrent.ExecutionContext, implicit futureTimeout: akka.util.Timeout)spray.client.pipelining.SendReceive.
Unspecified value parameter executionContext.
    val pipeline = sendReceive
               ^
Run Code Online (Sandbox Code Playgroud)

我的代码是:

import scala.util.{Success, Failure}
import scala.concurrent.duration._
import akka.actor.ActorSystem
import akka.pattern.ask
import akka.event.Logging
import akka.io.IO
import spray.can.Http
import spray.client.pipelining._
import spray.util._
import argonaut._, Argonaut._

object test {

case …
Run Code Online (Sandbox Code Playgroud)

scala spray-json argonaut spray-client

10
推荐指数
1
解决办法
1万
查看次数

使用Argonaut或Circe更新不完整JSON的案例类

我需要从一个case类实例创建一个更新的实例(带有任何需要DecodeJson的隐式派生),给定一个不完整的json(缺少一些字段).如何通过Argonaut(最好)或Circe(如果必须的话)实现这一目标?

例:

case class Person(name:String, age:Int)
val person = Person("mr complete", 42)
val incompletePersonJson = """{"name":"mr updated"}"""
val updatedPerson = updateCaseClassFromIncompleteJson(person, incompletePersonJson)

println(updatedPerson)
//yields Person(mr updated, 42) 
Run Code Online (Sandbox Code Playgroud)

我很确定我必须将json解析为json AST,然后将其转换为Shapeless LabelledGeneric,然后以某种方式使用Shapeless更新来更新case类实例.


编辑2

在阅读了Shapeless源代码后,我发现我可以生成自己的"默认"对象.我设法创建了一个解决方案,它需要在解析json时出现case类的实例.我希望避免这种情况,而是稍后提供实例.无论如何它是:

import shapeless._
import argonaut._
import ArgonautShapeless._
import shapeless.ops.hlist.Mapper

case class Person(name: String, age: Int)

object MkDefault {

  object toSome extends Poly1 {
    implicit def default[P] = at[P](Some(_))
  }

  def apply[P, L <: HList, D <: HList]
  (p: P)
  (implicit
   g: Generic.Aux[P, L],
   mpr: Mapper.Aux[toSome.type, L, …
Run Code Online (Sandbox Code Playgroud)

json scala shapeless argonaut circe

10
推荐指数
1
解决办法
1480
查看次数

使用scala argonaut编码嵌套类

我正在尝试编码/解码以下案例类

case class Person(name: String, age: Int, childs: List[Person])
Run Code Online (Sandbox Code Playgroud)

使用以下代码:

object Person {
    implicit def PersonCodecJson =
        casecodec3(Person.apply, Person.unapply)("name", "age", "childs")

}
Run Code Online (Sandbox Code Playgroud)

与argonaut,但我得到以下编译器错误:

could not find implicit value for evidence parameter of type argonaut.EncodeJson[List[Person]]
Run Code Online (Sandbox Code Playgroud)

显然,编译器不知道如何处理List [Person]的编码,因为它在如何编码Person的定义中使用.

是否有一种聪明的方式告诉argonaut如何以正确的方式对其进行编码?

更新:感谢Travis:现在正在编译,但它无法正常工作.

implicit def PersonCodecJson : CodecJson[Person] =
        casecodec3(Person.apply, Person.unapply)("name", "age", "childs")
Run Code Online (Sandbox Code Playgroud)

导致无限递归和尝试解码的堆栈溢出

val input = """
    [{"name": "parent1", "age": 31, "childs": [{"name": "child1", "age": 2, "childs": []}]},
     {"name": "parent2", "age": 29, "childs": []}
    ]
    """
val persons = input.decodeOption[List[Person]].getOrElse(Nil)
Run Code Online (Sandbox Code Playgroud)

结果是

at Person$.PersonCodecJson(main.scala:8) …
Run Code Online (Sandbox Code Playgroud)

scala argonaut

9
推荐指数
1
解决办法
2081
查看次数

使用Scala Argonaut解析JSON数组

我正在使用Scala&Argonaut,尝试解析以下JSON:

[
    {
        "name": "apple",
        "type": "fruit",
        "size": 3
    },
    {
        "name": "jam",
        "type": "condiment",
        "size": 5
    },
    {
        "name": "beef",
        "type": "meat",
        "size": 1
    }
]
Run Code Online (Sandbox Code Playgroud)

而奋力工作,如何进行迭代,把值到一个List[MyType]地方MyType都会有名称,类型和大小等属性.

我将很快发布更具体的代码(我尝试了很多东西),但基本上我想了解光标的工作方式,以及如何遍历数组等.我尝试使用\\(downArray)移动到头部数组,然后:->-迭代数组,然后--\(downField)不可用(至少IntelliJ不这么认为).所以问题是我如何:

  • 导航到数组
  • 遍历数组(并知道我什么时候完成)
  • 提取每个字段的字符串,整数等值 - jdecode[String]as[String]

json scala argonaut

7
推荐指数
1
解决办法
2241
查看次数

Argonaut CodecJson和解码子类型

在Argonaut DecodeJson特性中,存在一种|||将解码器链接在一起的方法,从而选择第一个后续解码器.还有一种类似的方法DecodeResult具有相同的效果.乍一看,好像其中一个是我们想要解码共同特征的多个子类型的东西.但是,我们如何实际做到这一点?

第一个问题是,参数|||必须是DecodeJson解码被调用者应该解码的类型的超类型(并且类似地DecodeResult).我希望这样的解码器能够解码常见超类型的所有子类型,所以这似乎是无限递归的一个秘诀!

asInstanceOf在定义CodecJson超类型时,我们可以使用以下丑陋的黑客来解决这个问题:

c => c.as[A] ||| c.as[Foo](implicitly[DecodeJson[B]].asInstanceOf[DecodeResult[Foo]])
Run Code Online (Sandbox Code Playgroud)

但是,当解码两个以上的子类型时仍然存在问题.假设有亚型A,BCFoo.现在怎么样?我们如何为这个解码表达式添加另一种替代方案?.asInstanceOf[DecodeResult[AnyRef]]将破坏解析结果的类型安全性(好像我们此时尚未丢弃类型安全性!).然后我们很快就会用掉4,5或6种替代方案.

编辑:我很乐意接受使用Argonaut解码超过2宽子类型层次结构的任何替代方法作为答案.

scala subtype argonaut

6
推荐指数
0
解决办法
431
查看次数

如何为所有 Java 枚举编写 Scala Argonaut 编解码器

我有一个使用一堆 Java 代码的 Scala 项目,例如这个 Java 源代码:

public enum Category { FOO, BAR };
Run Code Online (Sandbox Code Playgroud)

然后我有一堆 Scala 案例类,我使用 Argonaut 将它们序列化为 JSON 或从 JSON 序列化,如下所示:

case class Thing (a: String, b: Int, c: Float)
object Thing {
  implicit val j = casecodec3 (Thing.apply, Thing.unapply)("a", "b", "c")
  implicit val e: Equal[Guild] = Equal.equal (_ == _)
}
Run Code Online (Sandbox Code Playgroud)

好的,现在我想编写一个使用 Java 枚举的 Scala 案例类,如下所示:

case class Thing (a: String, b: Int, c: Float, d: Category)
object Thing {
  implicit val j = casecodec4 (Thing.apply, Thing.unapply)("a", …
Run Code Online (Sandbox Code Playgroud)

scala argonaut

5
推荐指数
0
解决办法
339
查看次数

使用Argonaut创建通用JSON转换器

我是Scala的新手,在这里我正在尝试创建一个基于Argonaut的通用json转换器.我试图搜索谷歌和stackoverflow,但到目前为止,我没有任何线索.

这是我的代码片段.

import org.springframework.http.converter.AbstractHttpMessageConverter
import org.springframework.http.{MediaType, HttpInputMessage, HttpOutputMessage}    
import scala.io.Source
import argonaut._,Argonaut._

case class Currency(code: String)
object Currency {
    implicit def CurrencyCodecJson: CodecJson[Currency] = casecodec1(Currency.apply, Currency.unapply)("code")
}

case class Person(firstName: String, lastName: String)
object Person {
    implicit def PersonCodecJson: CodecJson[Person] = casecodec2(Person.apply, Person.unapply)("firstName", "LastName")
}

class ArgonautConverter extends AbstractHttpMessageConverter[Object](new MediaType("application", "json", Charset.forName("UTF-8")), new MediaType("application", "*+json", Charset.forName("UTF-8"))) {
    val c = classOf[Currency]
    val p = classOf[Person]

    def writeInternal(t: Object, outputStream: OutputStream) = {
        val jsonString = t match {
            case c:Currency …
Run Code Online (Sandbox Code Playgroud)

generics json scala argonaut

4
推荐指数
1
解决办法
1464
查看次数

使用Argonaut在JSON数组上进行映射

我很难通过Argonaut文档,所以我想我只想问一个简单的例子.

val input = """{"a":[{"b":4},{"b":5}]}"""

val output = ??? // desired value: List(4, 5)
Run Code Online (Sandbox Code Playgroud)

我可以将光标放到数组中:

Parse.parse(input).map((jObjectPL >=> jsonObjectPL("a") >=> jArrayPL)(_))
// scalaz.\/[String,Option[scalaz.IndexedStore[argonaut.Argonaut.JsonArray,
//  argonaut.Argonaut.JsonArray,argonaut.Json]]] =
// \/-(Some(IndexedStoreT((<function1>,List({"b":4}, {"b":5})))))
Run Code Online (Sandbox Code Playgroud)

但那又怎样?我是在正确的轨道上吗?我甚至应该使用游标吗?

编辑 - 我想这是一些进展.我为列表写了一个解码器:

Parse.parse("""[{"b": 4}, {"b": 5}]""")
  .map(_.as(IListDecodeJson(DecodeJson(_.downField("b").as[Int]))))
// scalaz.\/[String,argonaut.DecodeResult[scalaz.IList[Int]]] =
// \/-(DecodeResult(\/-([4,5])))
Run Code Online (Sandbox Code Playgroud)

编辑 - 慢慢开始把它放在一起......

Parse.parse(input).map(_.as[HCursor].flatMap(_.downField("a").as(
  IListDecodeJson(DecodeJson(_.downField("b").as[Int])))))
// scalaz.\/[String,argonaut.DecodeResult[scalaz.IList[Int]]] =
// \/-(DecodeResult(\/-([4,5])))
Run Code Online (Sandbox Code Playgroud)

编辑 - 所以我想到目前为止我的最佳解决方案是:

Parse.parse(input).map(_.as(
  DecodeJson(_.downField("a").as(
    IListDecodeJson(DecodeJson(_.downField("b").as[Int])).map(_.toList)
  ))
))
Run Code Online (Sandbox Code Playgroud)

但是感觉有点冗长.

scala scalaz argonaut

4
推荐指数
1
解决办法
1361
查看次数

`circe`类型级Json =>一个函数?

使用circe或者argonaut,我怎么能写一个Json => A(注释 - Json可能不是类型的名称)ASSN类给出的位置:

  // A USA Social Security Number has exactly 8 digits.
  case class SSN(value: Sized[List[Nat], _8])
Run Code Online (Sandbox Code Playgroud)

伪代码:

// assuming this function is named f

f(JsArray(JsNumber(1)))A因为它的大小是1而不会成为一个

f(JsArray(JsNumber(1), ..., JsNumber(8))) === SSN(SizedList(1,...,8))

scala argonaut circe

4
推荐指数
1
解决办法
328
查看次数