πŸ€μ€‘μ²©λœ JSON을 Java Object 둜 λ§€ν•‘ν•˜λŠ” 방법1 (With Jackson)

졜재혁·2022λ…„ 9μ›” 15일
7
post-thumbnail

🀨 λ“€μ–΄κ°€λ©°

λ‘€ 전적 검색 μ‚¬μ΄νŠΈλ₯Ό λ§Œλ“€κΈ° μœ„ν•΄ Riot Api λ₯Ό λ°›μ•„μ™€μ„œ Java 객체에 λ§€ν•‘μ‹œν‚€λ˜ μž‘μ—…μ„ ν•˜λ˜ 쀑, Response body 둜 λ„˜μ–΄μ˜¨ JSON 응닡 λ°μ΄ν„°μ˜ μƒνƒœκ°€ μ‹¬μƒμΉ˜ μ•Šμ€ 것을 λ°œκ²¬ν–ˆμŠ΅λ‹ˆλ‹€.

"info": {
        "gameCreation": 1662939391488,
        "mapId": 11,
        "participants": [
            {
                "assists": 3,
                "baronKills": 0,
                "basicPings": 1,
                "bountyLevel": 0,
                "challenges": {
                    "12AssistStreakCount": 0,
                    "abilityUses": 220,                  
                },
                "champExperience": 14906,
                "champLevel": 16,
                "perks": {
                    "statPerks": {
                        "defense": 5003,
                        "flex": 5008,
                        "offense": 5005
                    },
                    "styles": [
                        {
                            "description": "primaryStyle",
                            "selections": [
                                {
                                    "perk": 8010,                                  

(벌써 μ–΄μ§€λŸ½λ‹€)

κ²Œμž„μ˜ 정보λ₯Ό κ°€μ Έμ˜€λŠ” Match-V5 api 의 (극히)일뢀인데, JSON 였브젝트 μ•ˆμ— μ€‘μ²©λœ 객체와 JSON 배열이 λ„ˆλ¬΄ λ§ŽμŠ΅λ‹ˆλ‹€. μ•„λ§ˆλ„ ν•˜λ‚˜μ˜ κ²Œμž„μ— ν¬ν•¨λœ 정보가 λ„ˆλ¬΄ λ§Žμ•„μ„œ 그런 λ“―ν•©λ‹ˆλ‹€. 데이터λ₯Ό 읽어보면 μ˜¨κ°– μžμ§ˆκ΅¬λ ˆν•œ μ •λ³΄κΉŒμ§€ μ£Όμ–΄μ§‘λ‹ˆλ‹€.

이 응닡을 μ–΄λ–»κ²Œ ν•˜λ©΄ Java 객체에 맀핑을 μ‹œν‚¬κΉŒλ₯Ό κ³΅λΆ€ν•˜λ‹€κ°€ 기둝겸 포슀트λ₯Ό μž‘μ„±ν•˜κ²Œ λ˜μ—ˆμŠ΅λ‹ˆλ‹€. κ°„λ‹¨ν•œ μ˜ˆμ‹œλ‘œ μ•Œμ•„λ΄…μ‹œλ‹€.


JSON μ†ŒμŠ€μ½”λ“œ

{
    "nation": "Korea",
    "name": "Minsu",
    "address": {
        "city": "Seoul",
        "gu": "Songpa",
        "apart": {
            "apartName": "JsonApart",
            "dong": "101",
            "ho": "1501"
        }
    }  
}

ν•œκ΅­μ˜ μ‚¬λŠ” 민수의 μ£Όμ†Œ 정보λ₯Ό λ³΄λ‚΄μ£ΌλŠ” Json λ°μ΄ν„°μž…λ‹ˆλ‹€. λ―Όμˆ˜λŠ” μ„œμšΈμ‹œ μ†‘νŒŒκ΅¬μ˜ Json μ•„νŒŒνŠΈ 101동 1501ν˜Έμ— μ‚΄κ³ μžˆλ„€μš”.

λ³΄μ‹œλ‹€μ‹œν”Ό 이 JSON은 2레벨 깊이의 μ€‘μ²©λœ JSON으둜 이루어져 μžˆμŠ΅λ‹ˆλ‹€. 이 JSON 데이터λ₯Ό 받아와 λ‹€μŒμ˜ Java 객체둜 λ§€ν•‘μ‹œν‚€κ³  μ‹ΆμŠ΅λ‹ˆλ‹€.


맀핑될 JAVA Object

public class Person {

    private String nation;
    private String name;
    private String city;
    private String apartName;
    
}

λ―Όμˆ˜κ°€ 맀핑될 Person 클래슀. ꡭ적, 이름, μ‚΄κ³ μžˆλŠ” λ„μ‹œμ™€ μ•„νŒŒνŠΈ 이름을 μ €μž₯ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.
μ΄λ•Œ, JSON이 μ€‘μ²©λœ κΉŠμ΄μ— 따라 Person의 ν•„λ“œλ“€μ„ λ‹€μŒκ³Ό 같이 λΆ„λ₯˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

  • 0레벨 깊이의 Property
    • nation
    • name
  • 1레벨 깊이의 Property
    • city
  • 2레벨 깊이의 Property
    • apartName

city 같은 κ²½μš°λŠ” address μ—μ„œ 뽑아내야겠고(1레벨 깊이),
apartName 은 μ€‘μ²©λœ apart μ—μ„œ apartName 을 뽑아내면 λ˜κ² λ„€μš”(2레벨 깊이).


맀핑 방법 3가지

μ΄μ œλΆ€ν„° ν•œλ²ˆ 맀핑을 μ§„ν–‰ν•΄λ΄…μ‹œλ‹€!
λ§€ν•‘ν•˜λŠ” 방법은 총 3가지가 μžˆλŠ”λ°μš”, λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

  1. μ–΄λ…Έν…Œμ΄μ…˜μ„ μ‚¬μš©ν•œ 맀핑
  2. JsonNodeλ₯Ό μ‚¬μš©ν•œ 맀핑
  3. μ‚¬μš©μžκ°€ μ •μ˜ν•œ JsonDeserializerλ₯Ό μ΄μš©ν•œ 맀핑

μ €λŠ” 였늘 1. μ–΄λ…Έν…Œμ΄μ…˜μ„ μ‚¬μš©ν•œ λ§€ν•‘λ§Œμ„ λ‹€λ£° μ˜ˆμ •μž…λ‹ˆλ‹€.

2. JsonNodeλ₯Ό μ‚¬μš©ν•œ 맀핑과, 3. μ‚¬μš©μžκ°€ μ •μ˜ν•œ JsonDeserializerλ₯Ό μ΄μš©ν•œ 맀핑은 κ΅¬ν˜„μ˜ κ΄€μ μ—μ„œλŠ” 같은 λ‘œμ§μ΄λΌλŠ” 언급이 있고, μ €λŠ” 일단 μ–΄λ…Έν…Œμ΄μ…˜μ„ μ‚¬μš©ν•œ λ§€ν•‘μœΌλ‘œ ν•΄κ²°ν•  것이기에...

λ§Œμ•½ μ–΄λ…Έν…Œμ΄μ…˜μ„ μ‚¬μš©ν•œ λ§€ν•‘λ§ŒμœΌλ‘œ 해결이 λ˜μ§€ μ•Šκ±°λ‚˜, 토이 ν”„λ‘œμ νŠΈλ₯Ό λ§ˆλ¬΄λ¦¬ν•˜λ©΄ λ‹€λ₯Έ ν¬μŠ€νŠΈμ—μ„œ λ‹€μ‹œ ν•œλ²ˆ 닀루어보도둝 ν•˜κ² μŠ΅λ‹ˆλ‹€.
ν˜Ήμ‹œ λ‹€λ₯Έ 맀핑 방법에 κ΄€ν•˜μ—¬ κ΄€μ‹¬μžˆμœΌμ‹  뢄듀은

https://www.baeldung.com/jackson-nested-values

Baeldung μ‚¬μ΄νŠΈλ₯Ό μ°Έκ³ ν•˜μ‹œλ©΄ λ˜κ² μŠ΅λ‹ˆλ‹€.


✨ μ–΄λ…Έν…Œμ΄μ…˜μ„ μ‚¬μš©ν•œ 맀핑

λ¨Όμ €, 1레벨 깊이의 city λ₯Ό 뽑아내기 μœ„ν•΄μ„œλŠ”, μ€‘μ²©λœ address 정보λ₯Ό Map으둜 ν’€μ–΄λ‚΄μ–΄(unpack), city 속성을 μΆ”μΆœν•΄μ•Ό ν•©λ‹ˆλ‹€.
λ§ˆμ°¬κ°€μ§€λ‘œ, 2레벨 깊이의 apartName λ₯Ό 뽑아내기 μœ„ν•΄μ„œ, μ€‘μ²©λœ apart JSON 객체λ₯Ό Map 으둜 ν’€μ–΄λ‚΄, apartName 속성을 μΆ”μΆœν•  κ²ƒμž…λ‹ˆλ‹€.

μ€‘μ²©λœ 속성을 ν’€μ–΄λ‚΄λŠ” 방법은, @JsonProperty 와 μ•½κ°„μ˜ λ‘œμ§μ„ Person ν΄λž˜μŠ€μ— μΆ”κ°€ν•˜λ©΄ λ©λ‹ˆλ‹€. λ§λ‘œλ§Œν•˜λ©΄ 이해가 잘 μ•ˆκ°€λ‹ˆ μ½”λ“œλ‘œ ν•œλ²ˆ λ³΄μ‹œμ£ .

public class Person {
    private String nation;
    private String name;
    private String city;
    private String apartName;
	
    // μ•„λž˜μ™€ 같이 μΆ”κ°€
    @SuppressWarnings("unchecked")
    @JsonProperty("address")
    private void unpackNested(Map<String,Object> address) {
        this.city = (String)address.get("city");
        Map<String,String> apart = (Map<String,String>)address.get("apart");
        this.apartName = apart.get("apartName");
    }
}

μ½”λ“œλ₯Ό μ‚΄νŽ΄λ³΄λ„λ‘ ν•˜κ² μŠ΅λ‹ˆλ‹€.

@SuppressWarnings("unchecked")

μ œλ„€λ¦­μ„ μ‚¬μš©ν•˜λŠ” κ²½μš°μ—, 무점검 ν˜•λ³€ν™˜μ„ ν–ˆμ„ μ‹œ 컴파일 κ²½κ³  메세지λ₯Ό 보게 λ©λ‹ˆλ‹€. 저희 μ½”λ“œμ—μ„œλŠ” ( Map<String,String> )address.get("apart"); λΆ€λΆ„μ—μ„œ κ²½κ³  메세지가 λ°œμƒν•  κ²ƒμž…λ‹ˆλ‹€. μ΄λ•Œ, @SuppressWarings("unchecked") μ–΄λ…Έν…Œμ΄μ…˜μ„ 톡해 κ²½κ³  메세지λ₯Ό μ–΅μ œν•  수 μžˆμŠ΅λ‹ˆλ‹€. ν•˜μ§€λ§Œ @SuppressWarnings("unchecked")λŠ” ν˜• μ•ˆμ „μ„±μ΄ ν™•μ‹€ν•  λ•Œλ§Œ μ‚¬μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€.

@JsonProperty("address")

μ€‘μ²©λœ JSON 객체인 addressλ₯Ό Map<String,Object> ν˜•μ‹μœΌλ‘œ unpackNested νŒŒλΌλ―Έν„°λ‘œ λ„˜μ–΄μ˜¨ address에 λ§€ν•‘μ‹œν‚€κΈ° μœ„ν•¨μž…λ‹ˆλ‹€. 말이 살짝 ν—·κ°ˆλ¦¬μ‹€ 수 μžˆλŠ”λ°, @JsonProperty(이름) μ–΄λ…Έν…Œμ΄μ…˜μ—μ„œ κ΄„ν˜Έ μ•ˆμ˜ "이름"은 JSON 객체의 keyλ₯Ό μ˜λ―Έν•œλ‹€κ³  μƒκ°ν•˜μ‹œλ©΄ λ©λ‹ˆλ‹€.

private void unpackNested(Map<String,Object> address) {
        this.city = (String)address.get("city");

JSON 객체인 address λŠ” Map<String,Object> νƒ€μž…μœΌλ‘œ νŒŒλΌλ―Έν„°λ‘œ λ„˜μ–΄μ™”μ£ . κ·Έ Mapμ—μ„œ keyκ°€ "city"인 valueλ₯Ό κΊΌλ‚΄ String 으둜 ν˜•λ³€ν™˜ν•΄μ£Όλ©΄, ν•„λ“œμ˜ private String city; 와 λ§€ν•‘λ©λ‹ˆλ‹€. -> 1레벨 깊이의 맀핑 μ™„λ£Œ

		Map<String,String> apart = (Map<String,String>)address.get("apart");
        this.apartName = apart.get("apartName");

Map<String,Object> νƒ€μž…μ˜ addressμ—μ„œ, keyκ°€ "apart"인 Valueλ₯Ό κΊΌλƒ…λ‹ˆλ‹€. μ΄λ•Œ 꺼내진 2레벨 깊이의 JSON 객체λ₯Ό Map<String, String>νƒ€μž…μœΌλ‘œ ν˜•λ³€ν™˜ν•΄μ„œ μƒˆλ‘œμš΄ Map apartλ₯Ό μƒμ„±ν•©λ‹ˆλ‹€. λ§ˆμ§€λ§‰μœΌλ‘œ Mapνƒ€μž…μ˜ apartμ—μ„œ, keyκ°€ "apartName" 인 Valueλ₯Ό κΊΌλ‚΄ ν•„λ“œμ˜ private String apartName κ³Ό λ§€ν•‘ν•©λ‹ˆλ‹€. -> 2레벨 깊이의 맀핑 μ™„λ£Œ

μ΄λ ‡κ²Œ 맀핑이 μ™„λ£Œλ©λ‹ˆλ‹€.


마치며..

그런데 μž‘μ„±ν•΄λ†“κ³  λ³΄λ‹ˆ, 제 Riot api의 μ‘λ‹΅μ²˜λŸΌ μ€‘μ²©λœ depthκ°€ 1,2 레벨 μˆ˜μ€€μ΄ μ•„λ‹Œ κ²½μš°μ—λŠ” μ–΄λ…Έν…Œμ΄μ…˜μ„ μ‚¬μš©ν•œ 맀핑이 κ·Έλ‹₯ 효율적으둜 λŠκ»΄μ§€μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. 맀 κΉŠμ΄λ§ˆλ‹€ Map을 μƒμ„±ν•˜λ©΄ μ˜€λ²„ν—€λ“œλ„ 증가할 것이고, 무엇보닀 μ½”λ“œ μƒμœΌλ‘œ μˆ˜λ§Žμ€ 반볡이 λ°œμƒν•  것 κ°™μŠ΅λ‹ˆλ‹€.
였늘 닀루지 μ•Šμ€ JsonNodeλ₯Ό μ‚¬μš©ν•œ 맀핑 μ½”λ“œλ₯Ό μ½μ–΄λ³΄λ‹ˆ 이게 λ‚«κ² λ‹€ μ‹Άλ„€μš”.
그러면 λ‹€μŒμ€ JsonNodeλ₯Ό μ‚¬μš©ν•œ 맀핑 포슀트λ₯Ό μž‘μ„±ν•˜κ² μŠ΅λ‹ˆλ‹€.

μ½μ–΄μ£Όμ…”μ„œ κ°μ‚¬ν•©λ‹ˆλ‹€! ν‹€λ¦° λ‚΄μš© 지적 ν™˜μ˜ν•©λ‹ˆλ‹€!


πŸ“šReference

https://www.baeldung.com/jackson-nested-values
https://www.baeldung.com/jackson-annotations
https://colinch4.github.io/2020-07-30/24/

profile
잘λͺ»λœ 고민은 μ—†μŠ΅λ‹ˆλ‹€

1개의 λŒ“κΈ€

comment-user-thumbnail
2022λ…„ 9μ›” 15일

WoW

λ‹΅κΈ€ 달기