바디를 만들 때마다 New Dictionary 를 여러 번 쓰고 한 겹씩 감싸는 일은 금방 길어집니다. 응답에서 값 하나를 꺼낼 때도 마찬가지입니다. 이 글에서는 그 과정을 짧게 줄여 주는 함수들을 살펴봅니다.
이 글에서 다루는 것
・ 바디를 한 줄로 만들기
・ 경로로 값 넣기와 꺼내기
・ 응답을 파싱하고 훑어보기
・ 형을 지정해서 꺼내기
JNew()
JObj(key1, value1, key2, value2, ...)
JArr(item1, item2, ...)
JArrFrom(source)
JSet(obj, key, value)
JPut(root, path, value)
JVal(any, path, [default])
JNum(any, path, [default])
JStr(any, path, [default])
JBool(any, path, [default])
JParse(jsonText)
JText(any)
JPretty(any)
JKeys(any)
JCount(any)
JHas(any, key)
바디를 한 줄로 만들기
JObj 는 열쇠와 값을 번갈아 받아 Dictionary를 만듭니다. JArr 는 JSON 배열이 되는 Collection을 만듭니다. 둘을 겹쳐 쓰면 바디 전체가 한 줄이 됩니다.
' 예전 방식
Dim unitData As Object, assignData As Object, body As Object
Set unitData = New Dictionary
unitData.Add "FORCE", "KN"
unitData.Add "DIST", "M"
Set assignData = New Dictionary
assignData.Add "1", unitData
Set body = New Dictionary
body.Add "Assign", assignData
' JObj 를 쓰면
Dim body As Object
Set body = JObj("Assign", JObj("1", JObj("FORCE", "KN", "DIST", "M")))
완성된 객체를 JSON 문자열로 바꾸는 것은 JText 입니다. 읽기 좋게 들여쓰려면 JPretty 를 씁니다.
Debug.Print JText(body)
' {"Assign":{"1":{"FORCE":"KN","DIST":"M"}}}
Debug.Print CallPut("/db/UNIT", JText(body))
배열이 필요할 때는 JArr 를, 이미 만들어 둔 VBA 배열이나 시트 범위를 배열로 바꿀 때는 JArrFrom 을 씁니다.
Set body = JObj("Assign", JObj("1", _
JObj("ITEMS", JArr(1, 2, 3))))
' 이미 있는 배열을 그대로
Set ids = JArrFrom(Array(11, 12, 13))
Set ids = JArrFrom(Range("A1:A10"))
빈 객체가 필요하면 JNew 이고, 만들어 둔 객체에 열쇠를 하나 더 넣을 때는 JSet 을 씁니다. 값이 객체든 아니든 똑같이 동작하므로 Set 을 붙일지 고민하지 않아도 됩니다.
Dim fields As Object
Set fields = JNew()
JSet fields, "X", 0
JSet fields, "Y", 0
JSet fields, "Z", 3.5
경로로 값 넣기와 꺼내기
깊이 들어간 값은 JPut 으로 한 번에 넣을 수 있습니다. 중간 객체가 없으면 알아서 만듭니다.
Dim body As Object
Set body = JNew()
JPut body, "Assign/1/X", 0
JPut body, "Assign/1/Y", 0
JPut body, "Assign/1/Z", 3.5
Debug.Print JText(body)
' {"Assign":{"1":{"X":0,"Y":0,"Z":3.5}}}
꺼낼 때는 JVal 입니다. Dictionary는 열쇠로, Collection은 1부터 세는 번호로 찾아갑니다. 경로가 없으면 지정한 기본값을 돌려줍니다.
Dim result As Object
Set result = JParse(CallGet("/db/NODE"))
Debug.Print JVal(result, "NODE/1/X")
Debug.Print JVal(result, "NODE/1/Z", 0) ' 없으면 0
응답을 파싱하고 훑어보기
JParse 는 응답 문자열을 Dictionary나 Collection으로 바꿉니다. 형식이 깨져 있으면 Nothing 을 돌려주므로 그것으로 실패를 판단할 수 있습니다.
Dim result As Object
Set result = JParse(CallGet("/db/NODE"))
If result Is Nothing Then
Debug.Print "응답을 해석하지 못했습니다"
Exit Sub
End If
무엇이 들어 있는지 모를 때는 JKeys, JCount, JHas 로 확인합니다.
Dim nodes As Object
Set nodes = JVal(result, "NODE")
Debug.Print JCount(nodes) ' 절점 개수
Debug.Print JHas(nodes, "1") ' 1번이 있는가
Dim k As Variant
For Each k In JKeys(nodes)
Debug.Print k & " : " & JNum(nodes, k & "/Z")
Next k
형을 지정해서 꺼내기
JVal 은 무엇이 나올지 모르는 Variant를 돌려줍니다. 숫자나 문자열로 바로 쓰고 싶다면 형이 정해진 세 함수를 쓰는 편이 안전합니다.
| 함수 | 돌려주는 형 | 값이 없거나 형이 다를 때 |
|---|---|---|
JNum(any, path, [default]) |
Double | default (기본 0) |
JStr(any, path, [default]) |
String | default (기본 "") |
JBool(any, path, [default]) |
Boolean | default (기본 False) |
Dim z As Double, unitName As String
z = JNum(result, "NODE/1/Z")
unitName = JStr(JParse(Unit()), "UNIT/1/DIST", "M")
💡 Tip
응답 구조가 어떻게 생겼는지 모를 때는 Debug.Print JPretty(JParse(CallGet("/db/NODE"))) 로 한 번 찍어 보면 경로를 바로 알 수 있습니다.