相关工具

过滤工具

JsonPath

JMESPath

参考:

特点: json 过滤器,library, 有 python 和 php 等语言对应的包

优势:

  • python 支持友好

jq

命令行工具

保存工具

jsonl – jsonlines

参考:

jq 语法

参考:

命令使用方法:

jq 'your expression /path/to/your_json_file'

例子:

  1. 第一个表达式需要是 .: 表示获得整个 json
  2. [{"k": "v"}, {"k1": "v1"}]:

    • 取得第 0 个dict: .[0]

      {"k": "v"}
      
    • 取得所有 dict: .[]

      {"k": "v"}
      {"k1": "v1"}
      
    • 取得所有 dict, 并制作成一个list: [.[]]

      1
      2
      3
      4
      5
      6
      7
      8
      
      [
        {
          "k": "v"
        },
        {
          "k1": "v1"
        }
      ]
    • 取得第0个dict 中的value: .[0].k.[0]."k".[0]["k"]

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      
      echo '[{"k": "v"}, {"k1": "v1"}]' | jq '.[0].k'
      "v"
      echo '[{"k": "v"}, {"k1": "v1"}]' | jq '.[0]."k"'
      "v"
      echo '[{"k": "v"}, {"k1": "v1"}]' | jq '.[0].["k"]'
      jq: error: syntax error, unexpected '[', expecting FORMAT or QQSTRING_START (Unix shell quoting issues?) at <top-level>, line 1:
      .[0].["k"]
      jq: 1 compile error
      echo '[{"k": "v"}, {"k1": "v1"}]' | jq '.[0]["k"]'
      "v"
      • 注意: ["k"] 这种使用 key 获得 value 的方法需要取消前面的 .
  3. {"k": [1, 2, 3]}

    • 取得value 中的 第 0 个 value: .k[0]

      1
      2
      
      echo '{"k": [1, 2, 3]}' |jq '.k[0]'
      1

jmspath

使用

参考:

  1. JMESPath Tutorial — JMESPath
  2. 数组 index: [12]
  3. dict key: key_name

    • 单个: key_name
    • 多级(只有 dict 嵌套): k1.k2.k3
  4. dict + array 嵌套: arr_name[index_num]

    • arr_name 是 key 名称
    • index_num 是特定 array 中的元素
  5. 切片

    • 对于数组 array 支持类似 python list 的切片
    • eg: arr[1:3]
  6. Projection(糢糊匹配),使用通配符"*"

    • 数组,糢糊匹配: arr[*]

      • arr 数组下的所有元素
    • dict, 糢糊匹配: key_name.*

      • key_name 下嵌套字典的所有元素
  7. Flattern Projection(展开), 运算符"[]"

    • 嵌套结构被展开一层
    • eg: "running", "stopped"], ["terminated", "running" –> ["running", "stopped", "terminated", "running"]

      • 注意:

        • 前者是 [*] 匹配结果,保持了嵌套层级
        • 后者是 [] 匹配结果,展开了一层嵌套
    • 展开两级,使用 [][]
  8. Filter Projections(过滤)

  9. 类似 linux pipe, 运算符 "|"

    • 传递处理结果给,下一个表达式,eg: people[*].first | [0]
  10. 多选,运算符","

    • eg: people[].[name, state.name]
  11. 函数

1
2
print(33)
import os

自定义类的 json 化

实现方法:

  • 通过 json.dumps(obj, default=your_convert_fun), 传入你的自定义函数,把给定的对象 obj 转换成可以 json 化的 python 对象
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import json


class Base:
    pass
    # def to_json(self):
    #     raise
    #     return json.dumps(self, default=lambda obj: obj.__dict__, sort_keys=True)


class Person(Base):
    name: str
    id: int

    def __init__(self, name: str, id: int):
        self.name = name
        self.id = id


class MyClass(Person):
    students: list[Person]

    def __init__(self, name, id, students):
        super().__init__(name, id)
        self.students = students

def test1():
    """Basic test"""
    d = Person(name="LL", id=3)
    score = Base()

    score.values = list(range(3))

    d.socre = score
    s = json.dumps(d, default=vars)
    print(s)
    # output: {"name": "LL", "id": 3, "socre": {"values": [0, 1, 2]}}

def test2():
    "Nested"
    class1 = MyClass(id=1, name="one", students=[Person("Lucy", 1), Person("Lily", 2)])

    s = json.dumps(class1, default=vars)
    print(s)
    # output: {"name": "one", "id": 1, "students": [{"name": "Lucy", "id": 1}, {"name": "Lily", "id": 2}]}

def test3():
    """special properties"""
    d = Person(name="LL", id=3)
    d._code = 1
    d.__code = 2
    d.__mycode__ = 3
    print(json.dumps(d, default=vars))


def test4():
    """drop special properties"""
    d = Person(name="LL", id=3)
    d._code = 1
    d.__code = 2
    d.__mycode__ = 3
    print(json.dumps(d, default=vars))
    # output: {"name": "LL", "id": 3, "_code": 1, "__code": 2, "__mycode__": 3}
    print(json.dumps(d, default=lambda obj: obj.__dict__))
    # output: {"name": "LL", "id": 3, "_code": 1, "__code": 2, "__mycode__": 3}

    print(json.dumps(d,default=lambda obj: {k:v for k, v in obj.__dict__.items() if not k.startswith('__')}))
    # output: {"name": "LL", "id": 3, "_code": 1}

def test5():
    """Drop special properties for Nested"""
    p1, p2 = Person("Lucy", 1), Person("Lily", 2)
    p1._score = 3
    p1.__score = 4
    p1.__score__ = 4
    class1 = MyClass(id=1, name="one", students=[p1, p2])

    s = json.dumps(class1, default=vars)
    print(s)
    # output: {"name": "one", "id": 1, "students": [{"name": "Lucy", "id": 1, "_score": 3, "__score": 4, "__score__": 4}, {"name": "Lily", "id": 2}]}
    print(json.dumps(class1, default=lambda obj: {k:v for k, v in obj.__dict__.items() if not k.startswith('__')}))
    # output: {"name": "one", "id": 1, "students": [{"name": "Lucy", "id": 1, "_score": 3}, {"name": "Lily", "id": 2}]}

test5()
# if __name__ == "__main__":

NaN 的 json 化

  1. json 不会把普通数据中的 float('nan') 转换成 None, 需要 做前处理