Play 2.0 用户指南 - 使用JSON库 -- 针对Scala开发者

Stella981
• 阅读 792

    概述

    使用JSON的推荐方式是使用 Play 的基于类的JSON库,位于play.api.libs.json下.

    该库构建于Jerkson之上,它是一个Scala包装者,基于一个超快的基于Java的JSON库,Jackson.

    这种方式的好处是,Java和Scala可以共享同样的库(Jackson),而Scala用户可以享受额外类型安全的好处。
    play.api.libs.json包中,包含了7个JSON数据类型:
        JsObject
        JsNull
        JsUndefined
        JsBoolean
        JsNumber
        JsArray
        JsString
   
    它们都继承自JsValue。
   
    解析JSON字符串

    你可以將任何的JSON字符串解析成JsValue。

val json: JsValue = Json.parse(jsonString)

    遍历JSON树

    只要你拥有一个JsValue,你就可以遍历该树。该API看起来很像Scala提供的使用NodeSeq遍历XML文档的方式.

val json = Json.parse(jsonString)

val maybeName = (json \ "user" \ name).asOpt[String]
val emails = (json \ "user" \\ "emails").map(_.as[String])

   注意使用 \ 遍历不会导致失败.你必须在末尾使用 asOpt[T]自行处理出错误情形,它將返回 None 如果值缺失的话.否则,你可以使用 as[T],以抛异常的方式处理失败,如果值丢失的话.

    Scala值转成Json

    As soon as you have a type class able to transform the Scala type to Json, it is pretty easy to

    generate any Scala value to Json. For example letʼs create a simple Json object:

    只要你有一个type class 你就能將Scala类型转成Json,很容易將任何的Scala值转成Json.例如让我们创建一个简单的Json对象:

val jsonNumber = Json.toJson(4)

  或者创建Json数组

val jsonArray = Json.toJson(Seq(1, 2, 3, 4))

    这里將Seq[Int]转成Json数组没任何问题。然而当Seq由异构的值组成时,情况將变得复杂:

val jsonArray = Json.toJson(Seq(1, "Bob", 3, 4))

    没办法將Seq[Any]转成Json。(Any可以是任何非Json格式支持的对象,对吧?)

    简单的选择是將它们做为Seq[JsValue]处理:

val jsonArray = Json.toJson(Seq(
  toJson(1), toJson("Bob"), toJson(3), toJson(4)
))

    现在让我们看看最后一个创建更复杂的Json对象的例子:

val jsonObject = Json.toJson(
  Map(
    "users" -> Seq(
      toJson(
        Map(
          "name" -> toJson("Bob"),
          "age" -> toJson(31),
          "email" -> toJson("bob@gmail.com")
        )
      ),
      toJson(
        Map(
          "name" -> toJson("Kiki"),
          "age" -> toJson(25),
          "email" -> JsNull
        )
      )
    )
  )
)

    它將产生如下Json结果:

val jsonObject = Json.toJson(
  Map(
    "users" -> Seq(
      toJson(
        Map(
          "name" -> toJson("Bob"),
          "age" -> toJson(31),
          "email" -> toJson("bob@gmail.com")
        )
      ),
      toJson(
        Map(
          "name" -> toJson("Kiki"),
          "age" -> toJson(25),
          "email" -> JsNull
        )
      )
    )
  )
)

    Json序列化

    將JsValue转成Json字符串形式很容易:

val jsonString: String = Json.stringify(jsValue)

其它选择

    上面讨论的基于类型的选择是推荐的形式,当然也不会限制你使用其它JSON库。
   
    例如,下面是一小段演示怎样將纯Scala对象转成JSON 对象,通过绑定的,基于反射的Jerkson。

import com.codahale.jerkson.Json._

val json = generate(
  Map( 
    "url"-> "http://nytimes.com",
    "attributes" -> Map(
      "name" -> "nytimes", 
      "country" -> "US",
      "id" -> 25
    ), 
    "links" -> List(
      "http://link1",
      "http://link2"
    )
  )
)

    处理Json请求

    处理Json请求

        一个 JSON 请求是一个使用 request body 搭载经验证的JSON内容的 HTTP 请求.它必须指定 Content-Type 为text/json或application/json mime类型。

    默认Action使用any content body parser,让你以JSON取值得request body 值(实际上是JsValue):

def sayHello = Action { request =>
  request.body.asJson.map { json =>
    (json \ "name").asOpt[String].map { name =>
      Ok("Hello " + name)
    }.getOrElse {
      BadRequest("Missing parameter [name]")
    }
  }.getOrElse {
    BadRequest("Expecting Json data")
  }
}

    更好的方法是自定义BodyParser,请求Play直接將body解析为JSON:

def sayHello = Action(parse.json) { request =>
  (request.body \ "name").asOpt[String].map { name =>
    Ok("Hello " + name)
  }.getOrElse {
    BadRequest("Missing parameter [name]")
  }
}

    注意:当使用JSON body parser的时候,request.body的值直接做为一个经验证的JsValue值。

    你可以通过在命令行中用curl测试:

curl 
  --header "Content-type: application/json" 
  --request POST 
  --data '{"name": "Guillaume"}' 
  http://localhost:9000/sayHello

    返回:

HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Content-Length: 15

Hello Guillaume

返回JSON响应

    前面的一些例子,我们接收JSON请求,但我们返回的是text/plain响应。
    让我们更改为一个有效的HTTP响应:

def sayHello = Action(parse.json) { request =>
  (request.body \ "name").asOpt[String].map { name =>
    Ok(toJson(
      Map("status" -> "OK", "message" -> ("Hello " + name))
    ))
  }.getOrElse {
    BadRequest(toJson(
      Map("status" -> "KO", "message" -> "Missing parameter [name]")
    ))
  }
}

    现在它返回:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 43

{"status":"OK","message":"Hello Guillaume"}
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
java将前端的json数组字符串转换为列表
记录下在前端通过ajax提交了一个json数组的字符串,在后端如何转换为列表。前端数据转化与请求varcontracts{id:'1',name:'yanggb合同1'},{id:'2',name:'yanggb合同2'},{id:'3',name:'yang
待兔 待兔
3个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
Flink on YARN部署快速入门指南
Apache Flink是一个高效、分布式、基于Java和Scala(主要是由Java实现)实现的通用大数据分析引擎,它具有分布式MapReduce一类平台的高效性、灵活性和扩展性以及并行数据库查询优化方案,它支持批量和基于流的数据分析,且提供了基于Java和Scala的API。  从Flink官方文档可以知道,目前Flink支持三大部署模式:Loca
Stella981 Stella981
3年前
Play 2.0 用户指南 - HTTP编程 --针对Scala开发者
   Play2.0的ScalaAPI位于play.api包下。      该API直接位于play顶级包中(而play.mvc是为Java开发者提供的)。对于Scala开发者,查阅play.api.mvc。    Actions,ControllersandResults   什么是Actio
Stella981 Stella981
3年前
Play For Scala 开发指南
PlayJson简介Play内置了一套JSON库,以帮助开发者简化JSON操作。目前Play的JSON库包含以下功能:Json对象与字符串之间互转Json对象和CaseClass之间互转Json数据校验Json格式之间互转Play的JSON库并不依赖于P
Stella981 Stella981
3年前
Android So动态加载 优雅实现与原理分析
背景:漫品Android客户端集成适配转换功能(基于目标识别(So库35M)和人脸识别库(5M)),导致apk体积50M左右,为优化客户端体验,决定实现So文件动态加载.!(https://oscimg.oschina.net/oscnet/00d1ff90e4b34869664fef59e3ec3fdd20b.png)点击上方“蓝字”关注我
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
unity将 -u4E00 这种 编码 转汉字 方法
 unity中直接使用 JsonMapper.ToJson(对象),取到的字符串,里面汉字可能是\\u4E00类似这种其实也不用转,服务器会通过类似fastjson发序列化的方式,将json转对象,获取对象的值就是中文但是有时服务器要求将传参中字符串中类似\\u4E00这种转汉字,就需要下面 publ