How to represent optional fields in spray-json?

前端 未结 6 978
伪装坚强ぢ
伪装坚强ぢ 2021-02-07 06:36

I have an optional field on my requests:

case class SearchRequest(url: String, nextAt: Option[Date])

My protocol is:

object Sea         


        
相关标签:
6条回答
  • For anyone who is chancing upon this post and wants an update to François Beausoleil's answer for newer versions of Spray (circa 2015+?), JsField is deprecated as a public member of JsValue; you should simply supply a list of tuples instead of JsFields. Their answer is spot-on, though.

    0 讨论(0)
  • 2021-02-07 07:20

    Easy.

    import cc.spray.json._
    trait MyJsonProtocol extends DefaultJsonProtocol {
      implicit val searchFormat = new JsonWriter[SearchRequest] {
        def write(r: SearchRequest): JsValue = {
          JsObject(
            "url" -> JsString(r.url),
            "next_at" -> r.nextAt.toJson,
          )
        }
      }
    }
    
    class JsonTest extends FunSuite with MyJsonProtocol {
    test("JSON") {
        val search = new SearchRequest("www.site.ru", None)
        val marshalled = search.toJson
        println(marshalled)
      }
    }
    
    0 讨论(0)
  • 2021-02-07 07:22

    Works for me (spray-json 1.1.1 scala 2.9.1 build)

    import cc.spray.json._
    import cc.spray.json.DefaultJsonProtocol._
    
    // string instead of date for simplicity
    case class SearchRequest(url: String, nextAt: Option[String])
    
    // btw, you could use jsonFormat2 method here
    implicit val searchRequestFormat = jsonFormat(SearchRequest, "url", "nextAt")
    
    assert {
      List(
        """{"url":"..."}""",
        """{"url":"...", "nextAt":null}""",
        """{"url":"...", "nextAt":"2012-05-30T15:23Z"}""")
      .map(_.asJson.convertTo[SearchRequest]) == List(
        SearchRequest("...", None),
        SearchRequest("...", None),
        SearchRequest("...", Some("2012-05-30T15:23Z")))
    }
    
    0 讨论(0)
  • 2021-02-07 07:23

    Use NullOptions trait to disable skipping nulls: https://github.com/spray/spray-json#nulloptions Example: https://github.com/spray/spray-json/blob/master/src/test/scala/spray/json/ProductFormatsSpec.scala

    0 讨论(0)
  • 2021-02-07 07:30

    You might have to create an explicit format (warning: psuedocodish):

    object SearchRequestJsonProtocol extends DefaultJsonProtocol {
        implicit object SearchRequestJsonFormat extends JsonFormat[SearchRequest] {
            def read(value: JsValue) = value match {
                case JsObject(List(
                        JsField("url", JsString(url)),
                        JsField("nextAt", JsString(nextAt)))) =>
                    SearchRequest(url, Some(new Instant(nextAt)))
    
                case JsObject(List(JsField("url", JsString(url)))) =>
                    SearchRequest(url, None)
    
                case _ =>
                    throw new DeserializationException("SearchRequest expected")
            }
    
            def write(obj: SearchRequest) = obj.nextAt match {
                case Some(nextAt) => 
                    JsObject(JsField("url", JsString(obj.url)),
                             JsField("nextAt", JsString(nextAt.toString)))
                case None => JsObject(JsField("url", JsString(obj.url)))
            }
        }
    }
    
    0 讨论(0)
  • 2021-02-07 07:30

    Don't know if this will help you but you can give that field a default value in the case class definition, so if the field is not in the json, it will assign the default value to it.

    0 讨论(0)
提交回复
热议问题