yaml은 json, xml과 같이 config data를 표현하기 위한 하나의 형식이다.
Fruit: Apple
Vegetable: Carrot
Liquid: Water
Meat: Chiken
Fruits:
- Orange
- Apple
- banana
Vegetables:
- Carrot
- Tomato
Banana:
Calories: 105
Fat: 0.4g
Carbs: 27g
Grapes:
Fat: 0.3g
Carbs: 16g
indentation에 있는 것을 조심하자. indentation이 다르면 상하 계층관계를 나누기 때문이다. 여기서는 Banana
가 상위이고, Calories
, Fat
, Carbs
가 하위 자식이다.
Fruits:
- Banana:
Calories: 105
Fat: 0.4g
Carbs: 27g
- Grape:
Calories: 62
Fat: 0.3g
Carbs: 16g
dictionary는 unordered이지만, list는 ordered이다.
Banana:
Calories: 105
Fat: 0.4g
Carbs: 27g
Banana:
Calories: 105
Carbs: 27g
Fat: 0.4g
위 두 Banana
는 서로 같은 Banana
이다. dictionary는 순서가 무의미 하기 때문이다.
그러나, 다음의 두 Fruits
는 서로 다르다.
Fruits:
- Orange
- Apple
- banana
```yaml
Fruits:
- Orange
- banana
- Apple
list는 순서가 유의미한 ordered이기 때문이다
json path는 json이나 yaml으로 된 format에서 json query로 데이터를 추출하는 방법이다.
가령 다음과 같은 json 파일이 있다고 하자.
{
"car": {
"color": "blue",
"price": "$20,000"
}
}
위 json 파일에서 json path로 query를 날리는 것이다.
car
이렇게 query를 보내면
{
"color": "blue",
"price": "$20,000"
}
다음의 결과가 나오는 것이다.
만약 여기서, car
의 color
를 추출하고 싶다면 다음과 같이 쓰면 된다.
car.color
결과는 예상하듯이 다음과 같다.
"blue"
그런데, 실제로는 위와 같이 query를 보내면 실패하는데, 이는 json
의 특성상 {}
로 처음에 감싸지기 때문이다.
{
...
}
즉 모든 json file들은 위와 같이 {}
으로 시작한다. 이를 root element
라고 한다. 이 root element
를 표현해주어야 하는데, $
으로 표현할 수 있다. 따라서, 위의 json query들을 다음과 같이 정리할 수 있다.
$.car
$.car.color
따라서, 반드시 $
으로 시작한다는 사실을 잊지 말도록 하자.
또한, json path query의 결과는 모두 []
로 감싸져서 나온다. 따라서 최종 결과는 다음과 같이 정리할 수 있다.
$.car
[
{
"color": "blue",
"price": "$20,000"
}
]
$.car.color
[
"blue"
]
[]
로 결과들이 감싸진다는 사실을 잊지말도록 하자.
다음은 json의 list일 때 어떻게 query를 보낼 수 있는 지 알아보자.
[
"car",
"bus",
"truck",
"bike"
]
list
이기 때문에 0부터 시작해서 원소 갯수만큼 인덱싱을 할 수 있다. 추가적으로 []
역시도 root element이기 때문에 []
로 감싸야한다.
$[0]
["car"]
결과는 무조건 []
안에 넣어진다는 사실을 잊지말자.
다음과 같이 여러개도 가져올 수 있다.
$[0, 3]
["car", "bike"]
다음은 복합 구조로, dictionary과 list가 합쳐진 구조이다.
{
"car": {
"color": "blue",
"price": "$20,000",
"wheels": [
{
"model": "X345ERT",
"location": "front-right"
},
{
"model": "X345GRX",
"location": "front-left"
},
{
"model": "X236DEM",
"location": "rear-right"
},
{
"model": "X987XMV",
"location": "rear-right"
}
]
}
}
여기서 두번째 wheels
의 model
명을 가져온다고 하자. 다음과 같이 query를 쓸 수 있다.
$.car.wheels[1].model
X345GRX
json path에서 특정 조건을 설정할 수도 있다.
[
12,
43,
23,
12,
56,
43,
93,
32,
45,
63,
27,
8,
78
]
여기서 40보다 큰 값만 가져오고 싶을 때 다음과 같이 쓸 수 있다.
$[?( @ > 40 )]
해석하자면 다음과 같다.
$
: root element[]
: list 중?()
: 조건 문@
: 각 element 순회?()
조건문 안에 @
로 각 element들의 조건 연산을 실행하는 것이다. 결과는 다음과 같다.
[
43,
56,
43,
93,
45,
63,
78
]
==
말고도 다음의 연산들이 있다.
@ == 40
@ in [40,43,45]
@ != 40
@ nin [40,43,45]
nin
은 not in
이다.
다시 해당 예제로 돌아와보자.
{
"car": {
"color": "blue",
"price": "$20,000",
"wheels": [
{
"model": "X345ERT",
"location": "front-right"
},
{
"model": "X345GRX",
"location": "front-left"
},
{
"model": "X236DEM",
"location": "rear-right"
},
{
"model": "X987XMV",
"location": "rear-right"
}
]
}
}
여기서 wheels
중에 location
이 rear-right
인 model만 가져오고 싶다고 하자. 다음과 같이 쓸 수 있다.
$.car.wheels[?( @.location == "rear-right" )].model
결과는 다음과 같다.
"X236DEM"
응용해서 list의 모든 element를 순회할 때는 [?(@)]
만 써도 된다. 그러면 모든 element를 순회한다.
이제 위에서 배운 json path query를 써보도록 하자. query를 사용하기 위해서는 jpath
를 사용하면 된다.
{
"property1": "value1",
"property2": "value2"
}
다음의 q1.json
파일에서 property1
의 data를 가져오고 싶다면 다음과 같이 쓸 수 있다.
cat ./q1.json | jpath $.property1
결과는 다음과 같다.
[
"value1"
]
cat ./q11.json | jpath $.prizes[?(@)].laureates[?( @.id == "914" )]
다음의 data가 있다고 하자.
{
"car": {
"color": "blue",
"price": "$20,000"
},
"bus": {
"color": "white",
"price": "$120,000"
}
}
다음의 data에서 car
의 color
를 얻는 방법은 다음과 같다.
$.car.color
결과는 다음과 같다.
["blue"]
그런데, car
뿐만 아니라, bus
도 얻고 싶다면 어떻게해야할까?? 더 나아가서 몇 개의 key
가 있는 지는 모르겠지만 각 key
에 대한 color
를 얻고 싶다면 어떻게 해야할까?? 이를 위해 사용하는 것이 바로 wildcard이다.
$.*.color
다음과 같이 *
로 wildcard를 사용하면 각 key에 대한 color들을 가져올 수 있다. 결과는 다음과 같다.
["blue", "white"]
wildcard
는 위와 같이 json file에서 각 key
에 대한 순회도 가능하지만, json file이 list일 때도 모든 요소에 대해서 순회가 가능하다.
[
{
"model": "X345ERT",
"location": "front-right"
},
{
"model": "X345GRX",
"location": "front-left"
},
{
"model": "X236DEM",
"location": "rear-right"
},
{
"model": "X987XMV",
"location": "rear-right"
}
]
위 data에서 각 list 요소에 대한 model
property를 얻어보도록 하자. 다음과 같이 쓸 수 있다.
$.*.model
list에 *
을 쓰는 것은 list의 모든 item을 순회한다는 의미이다.
["X345ERT", "X345GRX", "X236DEM", "X987XMV"]
다음의 데이터는 json key와 list가 혼재되어 있는 데이터이다.
{
"car": {
"color": "blue",
"price": "$20,000",
"wheels": [
{
"model": "X345ERT",
},
{
"model": "X345GRX",
}
]
},
"bus": {
"color": "white",
"price": "$120,000",
"wheels": [
{
"model": "X236DEM",
},
{
"model": "X987XMV",
}
]
}
}
모든 model명을 얻고 싶다면 다음과 같이 쓸 수 있다.
$.*.wheels[*].model
[
"X345ERT", "X345GRX","X236DEM","X987XMV"
]
json path에서 list에 대한 slice연산도 가능하다.
[
"Apple",
"Google",
"Microsoft",
"Amazon",
"Facebook",
"Coca-Cola",
"Samsung",
"Disney",
"Toyota",
"McDonald's"
]
다음의 경우에 Apple
, Google
, Microsoft
를 얻고 싶다면 다음과 같이 쓸 수 있다.
$[0:3]
start~end로 end는 포함하지 않는다.
[
"Apple",
"Google",
"Microsoft"
]
거꾸로 인덱싱하는 것도 가능하다. -1부터 시작해서 인덱스하면 된다. 정리하면 다음과 같다.
[
"Apple", ... 0, -10
"Google", ... 1, -9
"Microsoft", ... 2, -8
"Amazon", ... 3, -7
"Facebook", ... 4, -6
"Coca-Cola", ... 5, -5
"Samsung", ... 6, -4
"Disney", ... 7, -3
"Toyota", ... 8, -2
"McDonald's" ... 9, -1
]
따라서, 다음과 같이 인덱싱도 가능하다.
$[-3:]
[
"Disney",
"Toyota",
"McDonald's"
]
참고로 -
연산은 잘 안될수도 있으니 다음과 같이 ''
을 감싸줘서 실행하는 것이 좋다.
jpath '$[-4:]'