본문 바로가기
공부/java & Spring

[Spring] json data parsing ... json file을 읽어와서 데이터 출력해보기

by 고기 2023. 4. 24.

1. 사용할 JSON DATA

2. 전체 테스트코드

3. file parsing

4. parsing JSONObject to JSONArray

5. Convert JSONArray's element to JSONArray

6. Convert JSONArray to JSONObject


 

까먹기전에 써놓자..

Spring에서 json file을 읽어와서 JSONArray / JSONObject로 변환 후 출력하는 과정을 정리해봤다.

근데 써놓고보니까 굉장히 비효율적인 것 같은데... 더 좋은 방법 있으면 다시 작성하는걸로...

 

1. 사용할 JSON DATA

테스트에 사용할 데이터는 maplestory 랭킹 정보 데이터가 저장되어 있 json data를 사용한다.

데이터는 크게 equipInfo, characterInfo, characterBasicInfo로 나뉘어있고 캐릭터 정보가 담겨있다.

근데 사용할 data의 길이가 너무 길어서 일부 생략했다.

{
  "equipInfo": [    
    {
      "equipCategory": "장비분류 | 모자",
      "equipName": "카오스 핑크빈 모자 ",
      "equipPotential": "해당 사항이 없습니다.",
      "equipElement": "카오스 핑크빈 모자 \n135\n0\n0\n0\n0\n장비분류 | 모자\nSTR\n+27\nDEX\n+27\nINT\n+43 (27 + 16 + 0)\nLUK\n+43 (27 + 16 + 0)\nMaxHP\n+1950 (0 + 1950 + 0)\n공격력\n+1\n마력\n+1\n물리방어력\n+200\n올스탯\n+5% (0% + 5%)\n업그레이드 가능 횟수\n10회\n가위 사용 가능 횟수\n10회\n잠재옵션\n해당 사항이 없습니다.\n에디셔널 잠재옵션\n해당 사항이 없습니다.\n최대 20성까지 강화 가능\n플래티넘 카르마의 가위를 사용하면 1회 교환이 가능하게 할 수 있습니다.",
      "equipImg": "https://avatar.maplestory.nexon.com/ItemIcon/KEPCIBMA.png",
      "equipAdditionalPotential": "해당 사항이 없습니다.",
      "equipImgPath": "\\getCharacterData\\equipImg\\카오스 핑크빈 모자.png",
      "equipNum": 3
    },    
    {
      "equipCategory": "장비분류 | 신발",
      "equipName": "펜살리르 메이지부츠 ",
      "equipPotential": "(레어 아이템)",
      "equipElement": "펜살리르 메이지부츠 \n레어아이템\n140\n0\n0\n0\n428\n착용 가능한 직업 | 마법사\n장비분류 | 신발\nINT\n+11\nLUK\n+10\nMaxHP\n+2520 (0 + 2520 + 0)\n마력\n+1\n물리방어력\n+50\n이동속도\n+11 (5 + 6 + 0)\n업그레이드 가능 횟수\n6회\n가위 사용 가능 횟수\n10회\n잠재옵션\n(레어 아이템)\n잠재능력이 봉인되어 있습니다.\n에디셔널 잠재옵션\n해당 사항이 없습니다.\n최대 25성까지 강화 가능\n실버 카르마의 가위를 사용하면 1회 교환이 가능하게 할 수 있습니다.",
      "equipImg": "https://avatar.maplestory.nexon.com/ItemIcon/KEPFJOIJ.png",
      "equipAdditionalPotential": "해당 사항이 없습니다.",
      "equipImgPath": "\\getCharacterData\\equipImg\\펜살리르 메이지부츠.png",
      "equipNum": 15
    },
    {
      "potentialB": "",
      "starForce": "",
      "equipName": "no",
      "pImgB": "\\layout\\images\\gif\\gifdownload\\",
      "pImgA": "\\layout\\images\\gif\\gifdownload\\",
      "sfImg": "",
      "pImg": "\\layout\\images\\potential\\",
      "potentialA": "",
      "potential": "",
      "equipNum": 29,
      "equipImgPath": "\\layout\\images\\overlay.png"
    },    
  ],
  "characterBasicInfo": {
    "defenseIgnore": "47%",
    "luk": "702",
    "hp": "21,000",
    "guild": "-",
    "world": "루나",
    "dex": "279",
    "criticalDamage": "25%",
    "ability": "버프 스킬의 지속 시간 33% 증가\nINT 6 증가, STR 3 증가\nSTR 8 증가, DEX 4 증가\n",
    "hyperStat": "데미지 18% 증가\n",
    "starForce": "10",
    "defensePower": "3414",
    "stat": "13,680 ~ 54,721",
    "famous": "365",
    "mp": "32,105",
    "int": "2,486",
    "str": "878",
    "stateResistance": "10",
    "moveSpeed": "127%",
    "money": "3,367,488",
    "bossAttack": "45%",
    "jumpPower": "122%",
    "maplePoint": "546",
    "job": "마법사/비숍",
    "fame": "26,749",
    "stance": "0%",
    "arcaneForce": "0"
  },
  "characterInfo": {
    "img": "https://avatar.maplestory.nexon.com/Character/180/GHPODNDAHACLNAPLCNLADBCKKFEPCOFOMOIEEOGCLNAJFAGAMBJLBPGGHPOBMGGELECKLBMFIIELEIBDMKJJMGECHCNLILODGJLCKDFAJLCPCPBAKMACLFMEMHJJAGKOPCPJBJKEJFPPPIPBGCPOGBMOBDDGJGOEIFPKOCJKEIFJPCNAJDINOILAPBLNIEFPMKALNCLFDKGKKJCFMEELCHCPMODNHFIPJAEGMAIHOGDCEKNCCEFPJMAGJBIALLAD.png",
    "level": "Lv.201",
    "name": "봄날의첫눈",
    "characterImgPath": "\\getCharacterData\\characterImg\\봄날의첫눈.png"
  }
}

 

2. 전체 테스트 코드

먼저 테스트용 컨트롤러를 하나 만들었다.

@SuppressWarnings("unchecked")
@GetMapping("/test")
public void test() throws IOException, ParseException {
    log.info("test");
    String sep = File.separator;
    String filePath = System.getProperty("user.dir") + sep + "src" + sep + "main" + sep + "resources"
            + sep + "static" + sep + "getCharacterData" + sep + "jsonData" + sep + "봄날의첫눈.json";

    JSONObject j = new JSONObject();
    JSONParser parser = new JSONParser();
    j = (JSONObject) parser.parse(new InputStreamReader(new FileInputStream(filePath), "UTF-8"));

    // <------------> //
    JSONArray jj = (JSONArray) j.get("equipInfo");
    log.info("jj:" + jj.size());
    log.info("jj:" + jj);

    for (int i = 0; i < jj.size(); i++) {
        // log.info("===>" + jj.get(i));

        JSONArray jjj = new JSONArray();
        jjj.add(jj.get(i));
        // log.info("-----" + jjj.get(0));
        // log.info("----------" + jjj.size());

        JSONObject jjjj = new JSONObject();
        jjjj = (JSONObject) jjj.get(0);
        // log.info("@@@@@" + jjjj);
        // log.info("@@@@@@@@@@" + jjjj.size());

        log.info("-------------");
        log.info("equipCategory -> " + jjjj.get("equipCategory"));
        log.info("equipName -> " + jjjj.get("equipName"));
        log.info("equipPotential -> " + jjjj.get("equipPotential"));
        log.info("equipAdditionalPotential -> " + jjjj.get("equipAdditionalPotential"));
        log.info("equipImgPath -> " + jjjj.get("equipImgPath"));
        log.info("-------------");
    }
}

 

3. file parsing

준비한 json file을 불러와서 JSONObject로 파싱해준다.

@SuppressWarnings("unchecked")
@GetMapping("/test")
public void test() throws IOException, ParseException {
    ### 1) file parsing ###
    String sep = File.separator;
    String filePath = System.getProperty("user.dir") + sep + "src" + sep + "main" + sep + "resources"
            + sep + "static" + sep + "getCharacterData" + sep + "jsonData" + sep + "봄날의첫눈.json";

    JSONObject j = new JSONObject();
    JSONParser parser = new JSONParser();
    j = (JSONObject) parser.parse(new InputStreamReader(new FileInputStream(filePath), "UTF-8"));
}

 

4. parsing JSONObject to JSONArray

JSONObject의 key를 꺼내서 JSONArray로 파싱해준다.

print는 equipInfo의 size와 equipInfo 전체를 출력한 결과다.

@SuppressWarnings("unchecked")
@GetMapping("/test")
public void test() throws IOException, ParseException {
    ### 1) file parsing ###
    String sep = File.separator;
    String filePath = System.getProperty("user.dir") + sep + "src" + sep + "main" + sep + "resources"
            + sep + "static" + sep + "getCharacterData" + sep + "jsonData" + sep + "봄날의첫눈.json";

    JSONObject j = new JSONObject();
    JSONParser parser = new JSONParser();
    j = (JSONObject) parser.parse(new InputStreamReader(new FileInputStream(filePath), "UTF-8"));
    
    ### 2) equipInfo print ###
    JSONArray jj = (JSONArray) j.get("equipInfo");
    log.info("jj:" + jj.size());
    log.info("jj:" + jj);        
}

--- print --- 
[2023-04-24 16:10:45] [INFO ] [characterCardController:112] - jj:30
[2023-04-24 16:10:45] [INFO ] [characterCardController:113] - jj:[{"equipCategory":"장비분류 | 반지","equipName":"어웨이크 링 (+3) ","equipPotential":"(유니크 아이템)","equipElement":"어웨이크 링 (+3) \n유니크아이템\ ...

 

5. Convert JSONArray's element to JSONArray

반복문을 사용해서 equipInfo의 Object들을 JSONArray로 변환시킨다.

먼저 equipInfo는 {"potentialB":"", "starForce":"",  ... ,"equipNum":29} 를 30개 가지고 있는 Object다. 

즉 equipInfo Object는 equipInfo.get(equipInfo).get(0) ~ equipInfo.get(equipInfo).get(29)를 가지고 있다.

 

print는 equipInfo.get(equipInfo).get(0)를 JSONArray로 변환시킨 후 출력한 결과다.

참고로 equipInfo.get(equipInfo).get(0)의 size가 1인 이유는 원소를 { } 하나만 가졌기 때문이다.

@SuppressWarnings("unchecked")
@GetMapping("/test")
public void test() throws IOException, ParseException {
    ### 1) file parsing ###
	String sep = File.separator;
    String filePath = System.getProperty("user.dir") + sep + "src" + sep + "main" + sep + "resources"
            + sep + "static" + sep + "getCharacterData" + sep + "jsonData" + sep + "봄날의첫눈.json";

    JSONObject j = new JSONObject();
    JSONParser parser = new JSONParser();
    j = (JSONObject) parser.parse(new InputStreamReader(new FileInputStream(filePath), "UTF-8"));
    
    ### 2) equipInfo print ###
    JSONArray jj = (JSONArray) j.get("equipInfo");
    log.info("jj:" + jj.size());
    log.info("jj:" + jj); 
    
    ### 3) convert equipInfo.get(i) to JSONArray ###
    for (int i = 0; i < jj.size(); i++) {
        log.info("===>" + jj.get(i));

        JSONArray jjj = new JSONArray();
        jjj.add(jj.get(i));
        log.info("-----" + jjj.get(0));
        log.info("----------" + jjj.size());
    }
}

--- print --- 
[2023-04-24 16:25:13] [INFO ] [characterCardController:120] - -----{"potentialB":"","starForce":"","equipName":"no", ...}
[2023-04-24 16:25:13] [INFO ] [characterCardController:121] - ----------1

 

6. Convert JSONArray to JSONObject

JSONArray의 Object를 JSONObject로 변환 후 출력해준다.

코드에서 equipInfo.get(0)의 size가 1이라서 왜 이렇게 하나 싶을텐데, 만약 equipInfo.get(0)의 object의 size가 1개 이상이라면 반복문을 사용해서 JSONArray를 JSONObject로 변환시켜줘야 한다.

 

아무튼, 변환시킨 JSONObject를 출력해보자.

print는 JSONArray를 JSONObject로 변환시킨 후 출력한 결과다.

@SuppressWarnings("unchecked")
@GetMapping("/test")
public void test() throws IOException, ParseException {
     ### 1) file parsing ###
	String sep = File.separator;
    String filePath = System.getProperty("user.dir") + sep + "src" + sep + "main" + sep + "resources"
            + sep + "static" + sep + "getCharacterData" + sep + "jsonData" + sep + "봄날의첫눈.json";

    JSONObject j = new JSONObject();
    JSONParser parser = new JSONParser();
    j = (JSONObject) parser.parse(new InputStreamReader(new FileInputStream(filePath), "UTF-8"));
    
    ### 2) equipInfo print ###
    JSONArray jj = (JSONArray) j.get("equipInfo");    
    
    ### 3) convert equipInfo.get(i) to JSONArray ###
    for (int i = 0; i < jj.size(); i++) {
        JSONArray jjj = new JSONArray();
        jjj.add(jj.get(i));   

        JSONObject jjjj = new JSONObject();
        jjjj = (JSONObject) jjj.get(0);
        log.info("@@@@@" + jjjj);
        log.info("@@@@@@@@@@" + jjjj.size());

        log.info("-------------");
        log.info("equipCategory -> " + jjjj.get("equipCategory"));
        log.info("equipName -> " + jjjj.get("equipName"));
        log.info("equipPotential -> " + jjjj.get("equipPotential"));
        log.info("equipAdditionalPotential -> " + jjjj.get("equipAdditionalPotential"));
        log.info("equipImgPath -> " + jjjj.get("equipImgPath"));
        log.info("-------------");
    }
}

[2023-04-24 16:34:45] [INFO ] [characterCardController:125] - @@@@@{"equipAdditionalPotential":"(레어 아이템)","equipImgPath":"path","equipNum":30, ...}
[2023-04-24 16:34:45] [INFO ] [characterCardController:126] - @@@@@@@@@@8
[2023-04-24 16:34:45] [INFO ] [characterCardController:128] - -------------
[2023-04-24 16:34:45] [INFO ] [characterCardController:129] - equipCategory -> 장비분류 | 기계 심장
[2023-04-24 16:34:45] [INFO ] [characterCardController:130] - equipName -> 페어리 하트 (+10)  8성 강화
[2023-04-24 16:34:45] [INFO ] [characterCardController:131] - equipPotential -> (유니크 아이템)
[2023-04-24 16:34:45] [INFO ] [characterCardController:132] - equipAdditionalPotential -> (레어 아이템)
[2023-04-24 16:34:45] [INFO ] [characterCardController:134] - equipImgPath -> path
[2023-04-24 16:34:45] [INFO ] [characterCardController:135] - -------------

 

끝!

댓글