闷骚闷秀▼ 2015▼ Scala json RFC6901 代码

M005.jsonpath-又一个RFC6901实现

RFC6901的Scala实现。并在语法层面进行了改进。

@陈宝仪 / 2015-07-09 / CC-BY-SA-3.0

谈谈轮子

先来看wikipedia上的几个定义

Reinventing the wheel may be an ironic cliche—-it is not clear when the wheel itself was actually invented. The modern “invention” of the wheel might actually be a “re-invention” of an age-old invention. Additionally, many different wheels featuring enhancements on existing wheels (such as the many types of available tires) are regularly developed and marketed.

Reinventing the square wheel is the practice of unnecessarily engineering artifacts that provide functionality already provided by existing standard artifacts (reinventing the wheel) and ending up with a worse result than the standard (a square wheel).

Preinventing the wheel involves delaying a task if it is expected to be undertaken later. An example would be, “We don’t want to preinvent the wheel” when discussing a solution to a problem when it is known that the solution is being developed elsewhere. It is not necessarily pejorative.

Redefining the wheel is the practice of coming up with new and often abstruse ways of describing things when the existing way of describing them was perfectly adequate.

稍微解释一下

重新发明轮子 当你增强或改进了现有轮子的功能,是可以重复发明轮子的。(可以有)

重新发明了个方轮子 不但没增强或改进现有轮子,而且做的比现有的轮子更烂。(避免)

预先发明轮子 已经存在的解决方案能完美的解决问题,就不要冒着延迟任务的风险预先发明轮子。(不推荐)

重新定义轮子 一个轮子已经能够用足够完美的方式定义出来,就不要再用一种新的复杂的方式再次定义了。(避免)

使用jsonpath

jsonpath是一款轻量级、兼容RFC6901、不依赖任何库、 支持Scala DSL以及字符串解析的轮子

使用jsonpath可以不用定义 繁杂的映射class,通过类似文件path的方式选择需要的元素进行下一步的业务处理。

下面有几种常见的user case

    val json =
      """
        |[
        |    155e+012,
        |    0.55,
        |    0,
        |    9,
        |    100,
        |    110e+12,
        |    110e12,
        |    110e-12,
        |    3,
        |    -100,
        |    [
        |        true,
        |        false,
        |        null
        |    ],
        |    {
        |        "a泉bc": 1.233e-10,
        |        "bcd": true,
        |        "b": null
        |    },
        |    {
        |        "": 1.233e-10,
        |        "bcd": true,
        |        "b": 1.23
        |    },
        |    false,
        |    null
        |]
      """.stripMargin

    val value = JSONPointer().read[List[Any]](new Path / -3 /("bcd", ""), json)
    assert(value === List(true, 1.233E-10))

    val value1 = JSONPointer().reduceRead[List[Any]](new Path / * /(*, (e: String) => e.contains("b")), json)
    assert(value1 === List(List(1.233E-10, true, null), List(true, 1.23)))

    val value2 = JSONPointer().reduceRead[Any](new Path / (1 -> -1) /(*, (_: String) == "b"), json)
    assert(value2 === List(null, 1.23))

    val value3 = JSONPointer().reduceRead[List[Any]](new Path /(*, (e: Int, size: Int) => e > 5 && e < size), json).filterNot(_ match {
      case e: JSONArray => true
      case e: JSONObject => true
      case _ => false
    })
    assert(value3 === List(1.1E14, 1.1E-10, 3, -100, false, null))

    val value4 = JSONPointer().reduceRead[Any](new Path / -1, json)
    assert(value4 === null)

    val value5 = JSONPointer().reduceRead[List[Any]](new Path /(*, _ < _ - 8), json)
    assert(value5 === List(1.55E14, 0.55, 0, 9, 100, 1.1E14, 1.1E14))

    val value6 = JSONPointer().reduceRead[List[Any]]("/*/*", json, List(None, Some((e: String) => e.contains("b"))))
    assert(value6 === List(List(1.233E-10, true, null), List(true, 1.23)))

    val value7 = JSONPointer().reduceRead[Any]("/-3/1", json)
    assert(value7 === NotFound)

对RFC6901进行的改进

三个操作符: , *

:用于JSONArray的区间选取

,用于JSONArray或JSONObject的多个选取

*用于JSONArray或JSONObject的全部选取

对于操作符*增加了Filter功能。可以方便的对各种元素进行过滤

三种Filter

Int=>Boolean用于JSONArray的元素过滤

(Int,Int)=>Boolean用于JSONArray的元素过滤,第二个参数表示JSONArray的size

String=>Boolean用于JSONObject的key过滤

##References

《M005.jsonpath-又一个RFC6901实现》 RFC6901的Scala实现。并在语法层面进行了改进。
题图:Reinventing the Wheel. Knowing when and how.