본문 바로가기
웹개발지식쌓기

[back] Gson과 JSONArray, 같은 데이터 다른 JSON 구조

by developer_j 2022. 6. 2.
728x90
반응형

api 개발하는데, JSON 생성 시 JSONArray(혹은 JSONObject)를 사용하는데 오류남.. 500 에러.. 흑
그 때 팀 내 다른 개발자가 Gson을 사용하는 걸 보고 나도 사용해봤는데
똑같은 데이터를 사용했는데 Gson은 오류가 안나고 JSONArray는 오류가 나더라
무슨 차이가 있는지 궁금해서 System.out.println으로 찍어봤는데 데이터가 다르길래 확인해봤다.
(근데 오류 원인은 못알아냄 ㅎ.. 데이터 유형이 문제인걸까?)

GSON, JSONArray 사용법 제대로 숙지하지 못한 상태로 확인하면서 정리해나가므로, 결론은 맨 아래에 있음

@RequestMapping(value = "/myInfoDataList", produces = "application/json; charset=UTF-8")
@ResponseBody
public JSONObject myInfoDataList(HttpServletRequest request, @ModelAttribute("myInfoData") MyInfoData myLectureRoomListVO, ModelMap model) {
	List<MyInfoData> list = myInfoDataRoomService.selectMyInfoDataList(myInfoData);
	
	Gson gson = new Gson();
						
	String json = gson.toJson(list);
	System.out.println("gson >> " + json);
	String json2 = new GsonBuilder().serializeNulls().create().toJson(list);
	System.out.println("gson2 >> " + json2);
	System.out.println("JSONArray >> " + JSONArray.fromObject(list).toString());
	
}

 

jsoneditoronline.org에서 변환

회사 데이터니까 .. 일단 가리고

어쨌든 위 캡쳐에 보이다시피 

1. gson으로 만들면, 기준은 모르겠지만 결과 JSON에 48 props 만 남음.(캡쳐내용)
gson builder를 사용해서 null값 제거 하고 json으로 만들면 91 props
JSONArray로 만들면 전체 총 92 props의 json으로 만들어짐

2. JSONArray로 생성된 JSON 데이터와, Gson으로 생성된 JSON 데이터를 비교해보면 눈에 띄게 차이 나는 것 : props의 수.
왜 차이가 나는가? 각각의 라이브러리는 조회된 데이터에서 어떤 데이터를 골라내서 json 으로 변환하는지 ?

3. 내가 정의한 MyInfoData 객체는 자식 객체이며, 부모 객체의 변수를 모두 합치면 91개의 변수가 존재함
(자식)MyInfoDataVO = 76 ( MyInfoDataVO extends InfoDataVO )
(부모1)InfoDataVO = 10 ( InfoDataVO extends InfoDataVO )
(부모1의 부모)BaseVO = 5 ( MyInfoDataVO extends InfoDataVO )

순수 변수 갯수는 91, 여기에 BaseVO에는 변수값에 따라 사용/미사용 텍스트를 반환하는 추가 getter 메서드 1개 존재

4. 그렇다면, 이렇게 정리해볼 수 있음
JSONArray 사용 시 
-> VO의 상속관계 상관없이, getter를 기준으로 변수를 생성하여 데이터 세팅 

(예)

class BaseVO {
	private String useYesNo = "";
	
	public String getUseYesNo() {
		return useYesNo;
	}
	public void setUseYesNo(String useYesNo) {
		this.useYesNo = useYesNo;
	}
	public String getUseYesNoTitle() {	// 변수가 따로 없지만 변수 값에 따라 text 반환
		return this.useYesNo.equals("Y") ? "사용" : "미사용";
	}
}

class AttachFileVO extends BaseVO {
	private long fileSeq = 0;
	private String fileUrl = "";
	
	public long getFileSeq() {
		return fileSeq;
	}
	public void setFileSeq(long fileSeq) {
		this.fileSeq = fileSeq;
	}
	public String getFileUrl() {
		return fileUrl;
	}
	public void setFileUrl(String fileUrl) {
		this.fileUrl = fileUrl;
	}
}

// 변수 갯수는 3개지만 getter 함수가 총 4개 이므로,
// JSONArray로 JSON 데이터를 만들었을 경우 4개의 키/밸류가 세팅됨.

-> 결과 데이터에 따르면, List객체, String[], MultipartFile, 일반 String 변수 등 전체 변환됨

Gson 사용 시 

-> 결과데이터에 따라 추측해보면, List객체 변수 6개, String[] 변수 1개, MultipartFile 변수 1개 = 총 8개 변수가 변환되지 않았음. 더불어 일반 String 변수도 35 개 변환되지 않음. props 갯수 맞음. 91 - 43 = 48
-> 확실하지는 않지만 Gson이 복합객체를 제외한 데이터만 변환하는 거라고 친다면, 일반 String 변수 35개는 왜 변환되지 않았는지? ==> VO객체 안에서 초기화를 해주고 있느냐에 따라 변환되지 않았음.

(예)

private String myName = "";	// 초기화 한 변수
private String mySchool;	// 초기화 하지 않은 변수

// 위의 변수를 포함한 객체를 JSON으로 만들었을 때,
// 변수 myName은 변환되었으나, mySchool은 변환 안됨(props에 포함되지 않음)

[ 결론 ]

- JSONArray는 VO객체의 상속관계 포함하여 getter 함수를 기준으로 JSON 데이터(키,값의 쌍)를 생성
- Gson은 VO객체의 상속관계를 포함하여 초기화된 변수를 기준으로 JSON 데이터를 생성(초기화가 되어있지 않을 경우, 값이 없다면 변환하지 않음.)

 


*** 최종 테스트 예제 ***

소스

// [ 소스 ]
public static class BaseMyVO {
    private String useYesNo = "";

    public String getUseYesNo() {
        return useYesNo;
    }
    public void setUseYesNo(String useYesNo) {
        this.useYesNo = useYesNo;
    }
    public String getUseYesNoTitle() {	// 변수가 따로 없지만 변수 값에 따라 text 반환
        return this.useYesNo.equals("Y") ? "사용" : "미사용";
    }
    public String getUseYesNoTitle2() {	// 변수가 따로 없지만 변수 값에 따라 text 반환
        return this.useYesNo.equals("") ? "값이 비었습니다." : "값이 비어있지 않습니다.";
    }
}

public static class AttachFileMyVO extends BaseMyVO {
    private long fileSeq;
    private String fileUrl;
    private String fileName = "";

    public long getFileSeq() {
        return fileSeq;
    }
    public void setFileSeq(long fileSeq) {
        this.fileSeq = fileSeq;
    }
    public String getFileUrl() {
        return fileUrl;
    }
    public void setFileUrl(String fileUrl) {
        this.fileUrl = fileUrl;
    }
    public String getFileName() {
        return fileName;
    }
    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

}

public static void main(String[] args) {
    AttachFileMyVO attachFileVO = new AttachFileMyVO();
    Gson gson = new Gson();
    //gson.toJson(attachFileVO);
    System.out.println("=== 초기화되지않은 변수인 AttachFileMyVO.fileUrl에 아무 값도 세팅하지 않은 경우 ===");
    System.out.println(JSONArray.fromObject(attachFileVO));
    System.out.println(gson.toJson(attachFileVO));

    System.out.println("=== 초기화되지않은 변수인 AttachFileMyVO.fileUrl에 \"testUrl\"이라는 값을 세팅한 경우 ===");
    attachFileVO.setFileUrl("testUrl");
    System.out.println(JSONArray.fromObject(attachFileVO));
    System.out.println(gson.toJson(attachFileVO));
}

결과

더보기

// [ 결과 ]
=== 초기화되지않은 변수인 AttachFileMyVO.fileUrl에 아무 값도 세팅하지 않은 경우 ===
[{"fileName":"","fileSeq":0,"fileUrl":"","useYesNo":"","useYesNoTitle":"미사용","useYesNoTitle2":"값이 비었습니다."}]
{"fileSeq":0,"fileName":"","useYesNo":""}
=== 초기화되지않은 변수인 AttachFileMyVO.fileUrl에 "testUrl"이라는 값을 세팅한 경우 ===
[{"fileName":"","fileSeq":0,"fileUrl":"testUrl","useYesNo":"","useYesNoTitle":"미사용","useYesNoTitle2":"값이 비었습니다."}]
{"fileSeq":0,"fileUrl":"testUrl","fileName":"","useYesNo":""}


흔하디 흔한 VO 객체를 List형태로 가져와 JSON으로 만드는 소스인데 일하면서 하루종일 파봐도 오류가 뜨는 이유를 아직도 모르겠다 ^^

 

+) gson 사용법 참조글

https://freemmer.tistory.com/119

 

gson 소개 및 사용법

gson 소개 및 사용법 예전에 Native (Android, iOS등)와 WAS 서버간의 통신시 사용하는 포맷은 여러 방식이 있었습니다. 그중에 대표적인 것으로 xml과 json이 있는데요. 요새는 json이 대세인듯 합니다. gson

freemmer.tistory.com

 

728x90
반응형