总的来说在scala体系下,对于习惯了java和c#这些常规开发的人来说,无论是akka-http还是play,就处理个json序列化与反序列化真他娘够费劲的。

根据经验,Json处理是比较简单的,但是Play和akka-http的序列化让我烦恼了不少时间,所以我从自己的角度记录一下Play的JSON处理,来理解play的思维方式。

一、官方文档

代码也都是从官方文档复制后重新整理的,下面是参考的官方文档下有几篇JSON的文章

Working with Json
  1. JSON basics
  2. JSON with HTTP
  3. JSON Reads/Writes/Format Combinators
  4. JSON automated mapping
  5. JSON Transformers

二、实体序列化例子

1.本例中使用的实体类

package serialize

case class Location(lat: Double, long: Double)
case class Resident(name: String, age: Int, role: Option[String])
case class Place(name: String, location: Location, residents: Seq[Resident])

2.序列化例子

import play.api.libs.json._
import play.api.libs.functional.syntax._
import serialize.{Location, Place, Resident} object PlayJsonTest{ def main(args:Array[String]):Unit={ implicit val locationReads = Json.reads[Location]
implicit val residentReads = Json.reads[Resident]
implicit val placeReads = Json.reads[Place] val json: JsValue = Json.parse("""
{
"name" : "Watership Down",
"location" : {
"lat" : 51.235685,
"long" : -1.309197
},
"residents" : [ {
"name" : "Fiver",
"age" : 4,
"role" : null
}, {
"name" : "Bigwig",
"age" : 6,
"role" : "Owsla"
} ]
}
""") val result: JsResult[Place] = Json.fromJson[Place](json) result match {
case JsSuccess(r: Place, path: JsPath) => println("Name: " + r.name)
case e: JsError => println("Errors: " + JsError.toJson(e).toString())
}
}
}

3.解释

一般的json序列化比较简单,有一个类似JsonManager的管理类,提供serialize(object obj)与deserialize<T>(string json)这样方法,一般不需要开发者做太多的工作,比较简单,也是基于这种认识,所以对play的json处理方式就会困惑。

原因是scala和akka系列声称自己是可伸缩的框架,面向大数据领域,他认为传统的方式是比较重的oo方式,而大数据的处理主要是批量处理数据,所以可能只是对批量数据的个别字段做简单的运算即可,不需要沉重的OOM,看他原文的描述:

Are we doomed to convert JSON to OO?

For a few years now, in almost all web frameworks (except recent JavaScript server side stuff maybe in which JSON is the default data structure), we have been used to get JSON from network and convert JSON (or even POST/GET data) into OO structures such as classes (or case classes in Scala). Why?

  • For a good reason : OO structures are “language-native” and allows manipulating data with respect to your business logic in a seamless way while ensuring isolation of business logic from web layers.
  • For a more questionable reason : ORM frameworks talk to DB only with OO structures and we have (kind of) convinced ourselves that it was impossible to do else… with the well-known good & bad features of ORMs… (not here to criticize those stuff)

Is OO conversion really the default use case?

In many cases, you don’t really need to perform any real business logic with data but validating/transforming before storing or after extracting. Let’s take the CRUD case:

  • You just get the data from the network, validate them a bit and insert/update into DB.
  • In the other way, you just retrieve data from DB and send them outside.

So, generally, for CRUD ops, you convert JSON into a OO structure just because the frameworks are only able to speak OO.

I don’t say or pretend you shouldn’t use JSON to OO conversion but maybe this is not the most common case and we should keep conversion to OO only when we have real business logic to fulfill.

4.总结

先要知道play的json的关注点,以及他的思维方式,对于这种思维方式的好与坏,其实也无所谓。

三、json4s

json4s是scala下使用OO方式可以很接近的方法,他也提供了一些play.json关注的类xpath查询的这种功能,参见json4s的github

在akka-http下实在是无法忍受从1个到24个类属性序列化的这种方式,所以可以是一个比较好的选择

json4s的sbt引用

"org.json4s" %% "json4s-jackson" % "3.6.2",

本例使用的实体还是上文的实体,对应的序列化代码为:


package org.netsharp.jsonoom

import java.text.SimpleDateFormat

import org.json4s._
import org.json4s.jackson.JsonMethods._
import org.json4s.jackson.Serialization object Json4sDemo { def main(args:Array[String]):Unit={ var json:String = """
{
"name" : "Watership Down",
"location" : {
"lat" : 51.235685,
"long" : -1.309197
},
"residents" : [ {
"name" : "Fiver",
"age" : 4,
"role" : null
}, {
"name" : "Bigwig",
"age" : 6,
"role" : "Owsla"
} ]
}
"""; // implicit val formats = Serialization.formats(NoTypeHints)
implicit val formats = new DefaultFormats {
override def dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
} var place:Place = Serialization.read[Place](json)
json = Serialization.write(place) println(json) //另外一种序列化接口
place = parse(json).extract[Place] }
}
 

总的来说,json4s和play.json思路类似,他们都是基于jackson的序列化

你说是不是play.json抄袭了json4s?

四、直接用Jackson进行序列化

这篇文章介绍了直接SCALA使用Jackson进行JSON序列化

但是也不是那么完美,集合只能用java的集合,bean不能使用Option[Double]这样的类型

Play中JSON序列化的更多相关文章

  1. C#中JSON序列化和反序列化

    有一段时间没有到博客园写技术博客了,不过每天逛逛博客园中大牛的博客还是有的,学无止境…… 最近在写些调用他人接口的程序,用到了大量的JSON.XML序列化和反序列化,今天就来总结下json的序列化和反 ...

  2. Net中JSON序列化和反序列化处理(日期时间特殊处理)

    0  缘由 笔者最近在web api端使用Json.Net进行序列化处理,而在调用端使用DataContractSerializer进行反序列化,遇到日期时间处理反序列化不成功[备注:笔者使用Net ...

  3. 在net中json序列化与反序列化 面向对象六大原则 (第一篇) 一步一步带你了解linq to Object 10分钟浅谈泛型协变与逆变

    在net中json序列化与反序列化   准备好饮料,我们一起来玩玩JSON,什么是Json:一种数据表示形式,JSON:JavaScript Object Notation对象表示法 Json语法规则 ...

  4. PHP中json序列化后中文的编码显示问题

    在接口返回数据中,我们经常会返回json或者xml格式,php的json序列化函数json_encode非常好用,但是默认会把中文编码为ASCII码(注意,很多人认为这是乱码,其实不是),尤其在调试接 ...

  5. 解决nodejs中json序列化时Date类型默认为UTC格式

    在nodejs中,json序列化时Date类型时,默认转为UTC格式. 如下图 上面只是一个例子,下面我用一个更具体化的例子来展示一个这个情况,我们在开发WEB项目中,经常用到Express组件, 我 ...

  6. 解决nodejs中json序列化时Date类型为UTC格式

    在nodejs中,json序列化时Date类型时,默认转为UTC格式. 如下图 zhupengfei@DESKTOP-HJASOE3 MINGW64 /d/MyProject/exp2 $ node ...

  7. .NET中JSON序列化(数据集转JSON)

    Json序列化和反序列化指的是:对象序列化为JSON,并可用于从 JSON 反序列化对象 在.net 3.5中已支持JSON,引用命名空间: using System.Web.Script.Seria ...

  8. Asp.Net Core中Json序列化处理整理

    一.Asp.Net Core中的Json序列化处理使用的是Newtonsoft.Json,更多参考:C# Newtonsoft.Json JsonSerializerSettings配置序列化操作,C ...

  9. 在net中json序列化与反序列化

    准备好饮料,我们一起来玩玩JSON,什么是Json:一种数据表示形式,JSON:JavaScript Object Notation对象表示法 Json语法规则: 数据在键值对中 数据由逗号分隔 花括 ...

随机推荐

  1. leetcode每日刷题计划-简单篇day7

    还没有背单词,头晕脑胀 Num 66 加一 Plus One 注意就是进位的时候最后一位,为了省两句代码,那几个语句顺序写反覆盖的乱七八糟 vector头部插入(a.begin(),被插入的数) 如果 ...

  2. 学习Flask框架

      # -*- encoding: utf-8 -*- #导包 from flask import Flask #建立flask对象 app = Flask(__name__) #使用flask路由器 ...

  3. 关于java使用POI导出ppt ,其中表格setText 失败问题

    1.导出ppt 必要的包 使用maven <dependency> <groupId>org.apache.poi</groupId> <artifactId ...

  4. 单片机课程设计——课程设计之四位加法计算器(2)(C代码)

    #include<reg52.h> typedef unsigned char uint8; typedef unsigned int uint16; sbit rw=P2^5; sbit ...

  5. time模块的学习

    time模块不在python35\lib的安装目录下,是因为该模块是用C语言编写,内置到python解释器中.各种时间格式相互转换关系: import time,datetime # print(ti ...

  6. 基于C/S 结构的IM即时通讯软件--下篇

    3.实现界面事件函数 客户端:单击" 进入" 按钮发送请求,如果要与服务器通信,必须要同时发送结构体信息描述发送内容,便于服务器处理. void CCase010Dlg::OnBn ...

  7. Jenkins+Git+Maven构建并部署springboot(构建多模块中的单个模块)

    主要思路:1.jenkins从git中拉取项目源码:jenkins使用maven构建并将生成的jar包通过shell脚本启动. 环境:环境:Centos7.Maven3.5.3.git(单机) 准备工 ...

  8. Linux 操作命令

    1. Linux 概述1.1. 内核版本    从技术角度来讲, Linux只是一个系统内核,一个内核并不是一套完整的操作系统.一套完整的操作系统应该包括内核. GNU应用程序库和工具.图形桌面环境等 ...

  9. 安装和破解Navicat

    这里的是安装目录,要记住 额外热任务在桌面创建一个快捷方式 点击完成之后先不要打开运行Navicat.exe这个主程序,把PatchNavicat.exe复制到你刚刚我们安装的路径,,不是你安装包的路 ...

  10. Python开发者年度调研,结果出乎意料!

    来源商业新知网,原标题:Python开发者年度调研:一半Python用户也用JS,2/3选择Linux系统 作为高级编程语言,Python的受欢迎程度近几年一直在往 上涨.每年,Python官方都会针 ...