使用Scala Parser解析JSON

本文来自: http://fair-jm.iteye.com 转截请注明出处

 

最近几天看了些文章(Learn by Example: Scala Parser CombinatorsAn Introduction To Scala Parser Combinators )学习了scala中的Parser的一些使用 这边以一个解析JSON的例子来记录一些笔记

 

首先是一些连接符(翻译自第一篇文章):

  • | 选择连接符,当左边或右边的Parser成功时成功。
  • ~ 序列连接符,当左右的Parser都成功时成功
  • ~> 和~类似 不同的是左边的结果不会包含在最后的结果中
  • <~ 和~类似 右边的结果不会包含在最后的结果中
  • ^^ 转换连接符,当左边的操作成功时可以通过这个连接符操作结果
  • rep repeat的意思 重复

 

如果说看起来比较难懂的话 在使用之后就会觉得容易理解得多

我没有学过编译原理(选修课没选惭愧...听到别人说一星期两节课要上两章就退缩了...) 对一些专用术语不是很理解 这边的Parser使用更加像是使用正则表达式(这主要也有继承了RegexParser的因素在)

 

首先看JSON的组成 从ECMA-404的文档中可以看到:



 主要有 object array number string bool(true|false) null 这几个元素构成

 

为了编码方便 我让类继承自JavaTokenParsers:

class JsonParser extends JavaTokenParsers

 对以上一些元素进行了定义(和ECMA-404的规范有些许差别 其实很多地方需要重写正则表达式的...)

//来自JavaTokenParser的floatingPointNumber parser
  def jNum: Parser[Double] = floatingPointNumber ^^ (_.toDouble) 

//stringLiteral 也来自JavaTokenParser 这边解析出来的结果会是例如"string"的形式 我们需要把双引号给去掉
  def jStr: Parser[String] = stringLiteral ^^ (s => s.substring(1, s.length() - 1)) 

//正则表达式会被隐式转换为Parser 
  def jBool: Parser[Boolean] = "(true|false)".r ^^ (_.toBoolean)

  def jNull: Parser[Null] = "null".r ^^ (t => null)

 

接下去还差对object和array的定义

在ECMA-404中他们的定义如下:



 

 其中他们内的value是可以包括所有类型的(包括object和array)

可能有多个 这样需要用到rep连接符

 

具体的编码不是很困难 scala的模式匹配用起来比较舒服:

这边将JsonArray转化为List的形式 将JsonObject转换为Map的形式:

  def term = jsonArray | jsonObject | jNum | jBool | jNull | jStr
  def jsonArray: Parser[List[Any]] = "[" ~> rep(term <~ ",?".r) <~ "]" ^^ (l => l)

//String也会被隐式转化为Parser的形式
  def jsonObject: Parser[Map[String, Any]] = "{" ~> rep((ident ~ ":" ~ jNum |
    ident ~ ":" ~ jBool | ident ~ ":" ~ jNull | ident ~ ":" ~ jsonObject | ident ~ ":" ~ jsonArray | ident ~ ":" ~ jStr) <~ ",?".r) <~ "}" ^^ {
    os =>
      var map = Map[String, Any]()
      os.foreach(o =>
        o match {
          case k ~ ":" ~ v => map = map ++ Map(k -> v)
        })
      map

  }

 

 

最后来实验一下:



 虽然number的形式有点问题(我用了JavaTokenParser中的一个Parser) 但总体结果还是正确的 使用起来也是相当简单

 

对于解析JSON来说 用scala提供的Parser并不困难 本文并未对其中的原理有任何描述 可以看上面参考的第二篇文章 里面有比较详尽的分析 

 

希望对初学scala的Parser的人有所帮助^_^

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值