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:]'