주 콘텐츠로 건너뛰기
기능별 활용 가이드 생성 편집

JSON 바디 만들기와 응답 읽기

바디를 만들 때마다 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"))) 로 한 번 찍어 보면 경로를 바로 알 수 있습니다.

 

0
컨텐츠가 도움이 되셨나요?