===== JSON 쓰기 =====
==== 1. 원칙 ====
처음에 JSONObject를 선언한 후, put함수로 값을 지정하면 JSON을 쓰게 된다.
// 최상단 JSON
val jsonDoc = JSONObject()
jsonDoc.put("name", "Luke Skywalker") // 왼족이 키이고 오른쪽은 밸류이다.
==== 2. 다층구조 JSON ====
JSON을 다층구조로 쓰기 위해서는 먼저, 하위 JSON을 위의 방식으로 만든 후에,
이를 다시 put함수로 넣어주면 된다.
아래 예제는 Custom Class를 하위구조로 하여 다층 JSON구조를 만든 것이다.
// Json 구조 만들기
fun setJsonElement(ofAssault: KindOfAssault, relationshipWithVictim: RelationshipWithVictim, attackedDate : String) : String
{
// 폭행 종류 JSON
val jsonAssault = JSONObject()
try {
jsonAssault.put("checkFamily", ofAssault.checkFamily)
jsonAssault.put("checkDating", ofAssault.checkDating)
jsonAssault.put("checkEnfant", ofAssault.checkEnfant)
jsonAssault.put("checkSchool", ofAssault.checkSchool)
jsonAssault.put("checkSenior", ofAssault.checkSenior)
jsonAssault.put("checkMedical", ofAssault.checkMedical)
jsonAssault.put("checkAirplane", ofAssault.checkAirplane)
jsonAssault.put("checkDriver", ofAssault.checkDriver)
jsonAssault.put("checkAssault", ofAssault.checkAssault)
} catch (e: JSONException) {
// TODO Auto-generated catch block
e.printStackTrace()
}
// 상대와의 관계 JSON
val jsonVictimRelation = JSONObject()
try {
jsonVictimRelation.put("spouse", relationshipWithVictim.spouse)
jsonVictimRelation.put("parents", relationshipWithVictim.parents)
jsonVictimRelation.put("family", relationshipWithVictim.family)
jsonVictimRelation.put("lover", relationshipWithVictim.lover)
jsonVictimRelation.put("friend", relationshipWithVictim.friend)
jsonVictimRelation.put("unaquaintance", relationshipWithVictim.unaquaintance)
jsonVictimRelation.put("etc", relationshipWithVictim.etc)
} catch (e: JSONException) {
// TODO Auto-generated catch block
e.printStackTrace()
}
// 최상단 JSON
val jsonDoc = JSONObject()
try {
jsonDoc.put("ofAssault", jsonAssault) // 폭행 종류 JSON
jsonDoc.put("relationshipWithVictim", jsonVictimRelation) // 상대와의 관계 JSON
jsonDoc.put("attackedDate", attackedDate) // 폭행당한 날짜 JSON
} catch (e: Exception) {
// TODO Auto-generated catch block
e.printStackTrace()
}
// val str = jsonDoc.toString()
//
// Log.d("JsonString : ", str)
return jsonDoc.toString()
}
==== 3. 데이터 클라스 ====
위에 쓰인 데이터클라스의 모양은 다음과 같다.
// 폭행의 종류
data class KindOfAssault(
var checkFamily : Boolean = false, // 가정폭력
var checkDating : Boolean = false, // 교제폭력(데이트폭력)
var checkEnfant : Boolean = false, // 아동폭행
var checkSchool : Boolean = false, // 학교폭력
var checkSenior : Boolean = false, // 노인폭행
var checkMedical : Boolean = false, // 의료인 폭행
var checkAirplane : Boolean = false, // 항공기 내 폭행
var checkDriver : Boolean = false, // 운전자 폭행
var checkAssault : Boolean = false // 일반 폭행
)
// 피고소인과의 관계
data class RelationshipWithVictim(
var spouse : Boolean = false, // 배우자
var parents : Boolean = false, // 존속
var family : Boolean = false, // 배주자 및 존속을 제외한 가족
var lover : Boolean = false, // 연인, 데이팅 폭력
var friend : Boolean = false, // 친구, 학교폭력
var unaquaintance : Boolean = false, // 모르는 사람
var etc : Boolean = false, // 기타
var etcDetail : String = "없음" // 기타 관계 기본값
)
// 피해상태
data class StatusOfTrauma(
var bloated : Boolean = false, // 부어오름(부종)
var blooded : Boolean = false, // 피가 남
var brokenBone : Boolean = false, // 뼈가 부러짐
var bruise : Boolean = false, // 멍
var nothing : Boolean = false, // 외부 상처 없음
var etc : Boolean = false, // 기타
var etcDetail: String = "없음" // 기타 기본 값
)
// 폭행 방법
data class MethodOfBattery(
var collar : Boolean = false, // 멱살잡다
var push : Boolean = false, // 밀침
var pull : Boolean = false, // 잡아당김
var punch : Boolean = false, // 주먹으로 때림
var kick : Boolean = false, // 발로 참
var throwing : Boolean = false, // 물건을 던짐
var throwingDetail : String = "", // 물건을 던질 때 물건의 종류
var waffe : Boolean = false, // 흉기를 휘두름
var waffeDetail : String = "", // 휘두르는 흉기의 종류
var etc : Boolean = false, // 기타
var etcDetail: String = "", // 기타 기본 값
)
===== Json 읽기 =====
==== 1. 원칙 ====
읽기는 위의 쓰기의 반대로 하면 된다.
어떠한 해당 string을 json으로 받아오는 것은 다음과 같다 .
val jsonElementObject = JSONObject(sueItem.jsonElements) // Json Elements 데이터 가져와서 JSON으로 변환
json으로 받아온 후 특정한 키 값을 받아오는 것은 다음과 같다.
val jsonElementObject = JSONObject(sueItem.jsonElements) // Json Elements 데이터 가져와서 JSON으로 변환
val jsonAssault = jsonElementObject.getString("attackedDate")
val attackedDate by remember { mutableStateOf(jsonAssault).toString())}
근데, 실무상으로는 getString()함수를 쓰기보다는 optString(키값, 대체단어)의 함수를 쓰는 것이 좋다.
만약 해당 키값이 JSON에 없으면 null 값으로 인하여 크래시가 발생하기 떄문이다. optString()은 만약 JSON에 해당 키값이 없으면 대체단어로 대체를 해준다.
따라서 위 예제는 아래와 같이 해주는게 좋다.
val jsonElementObject = JSONObject(sueItem.jsonElements) // Json Elements 데이터 가져와서 JSON으로 변환
val jsonAssault = jsonElementObject.optString("attackedDate", "2024년 10월 20일")
val attackedDate by remember { mutableStateOf(jsonAssault).toString())}
==== 2. 특정 하위구조를 읽어오기 ====
특정한 Custom한 Class를 JSON에서 받아 오는 것은 다음과 같다.
// 폭행 종류 JSON 받아오기
fun getJsonAssault(jsonObject: JSONObject) : KindOfAssault {
val jsonAttackObject = jsonObject.getJSONObject("ofAssault")
val valueOfKindOfAssault : KindOfAssault = KindOfAssault(
checkFamily = jsonAttackObject.optString("checkFamily", "false").toBoolean(),
checkDating = jsonAttackObject.optString("checkDating","false").toBoolean(),
checkEnfant = jsonAttackObject.optString("checkEnfant", "false").toBoolean(),
checkSchool = jsonAttackObject.optString("checkSchool", "false").toBoolean(),
checkSenior = jsonAttackObject.optString("checkSenior", "false").toBoolean(),
checkMedical = jsonAttackObject.optString("checkMedical", "false").toBoolean(),
checkAirplane = jsonAttackObject.optString("checkAirplane", "false").toBoolean(),
checkDriver = jsonAttackObject.optString("checkDriver", "false").toBoolean(),
checkAssault = jsonAttackObject.optString("checkAssault", "false").toBoolean()
)
Log.d("jsonAssault", jsonAttackObject.toString())
return valueOfKindOfAssault
}
==== 3. 해당 JSON요소가 없을 경우를 대비한 에러처리 추가 ====
만약 JSON카테고리가 없을 경우 위의 optstring과 같은 기능을 하는 함수가 필요하다. 따라서 다음과 같이 고쳐주면 된다.
// 폭행 방법 JSON 받아오기
fun getJsonMethodOfBattery(jsonObject: JSONObject) : MethodOfBattery {
// 만약 없는 경우 더미를 만들기
if (jsonObject.isNull("methodOfBattery"))
{
// 피해상태
val jsonMethod = JSONObject()
try {
jsonMethod.put("collar", "false")
jsonMethod.put("push", "false")
jsonMethod.put("pull", "false")
jsonMethod.put("punch", "false")
jsonMethod.put("kick", "false")
jsonMethod.put("throwing", "false")
jsonMethod.put("throwingDetail", "")
jsonMethod.put("waffe", "false")
jsonMethod.put("waffeDettail", "")
jsonMethod.put("etc", "false")
jsonMethod.put("etcDetail", "")
jsonObject.put("methodOfBattery", jsonMethod) // 피해상태 JSON
}catch (e: JSONException) {
e.printStackTrace()
}
}
// JSON 받아오기
val jsonMethodObject = jsonObject.getJSONObject("methodOfBattery")
val valueOfMethod : MethodOfBattery = MethodOfBattery(
collar = jsonMethodObject.optString("collar", "false").toBoolean(),
push = jsonMethodObject.optString("push", "false").toBoolean(),
pull = jsonMethodObject.optString("pull", "false").toBoolean(),
punch = jsonMethodObject.optString("punch", "false").toBoolean(),
kick = jsonMethodObject.optString("kick", "false").toBoolean(),
throwing = jsonMethodObject.optString("throwing", "false").toBoolean(),
throwingDetail = jsonMethodObject.optString("throwingDetail", ""),
waffe = jsonMethodObject.optString("waffe", "false").toBoolean(),
waffeDetail = jsonMethodObject.optString("waffeDetail", ""),
etc = jsonMethodObject.optString("etc", "false").toBoolean(),
etcDetail = jsonMethodObject.optString("etcDetail", "없음")
)
return valueOfMethod
}
===== 참고 =====
==== 1. Json 스트링에서 Json 요소 읽기 ====
Json 요소를 뽑아내는 코드는 다음과 같다.
val json = LoadFileFromUri(uri = result.value, contentResolver)
// Json 문장에서 Json 요소 뽑아내기
try {
val jsonObject : JSONObject = JSONObject(json);
predictions.value = jsonObject.getString("predictions")
val jsonArray : JSONArray = JSONArray(predictions.value)
for (i in 0..jsonArray.length())
{
val subjsonObject : JSONObject = jsonArray.getJSONObject(i)
description.value += "description : " + subjsonObject.getString("description") + "\n" + "id : " + subjsonObject.getString("id") + "\n"
val structured_formatting : String = subjsonObject.getString("structured_formatting");
val subJsonObject2 : JSONObject = JSONObject(structured_formatting);
main_text.value += subJsonObject2.getString("main_text") + "\n"
}
} catch (e : JSONException) {
e.printStackTrace();
}
==== 2. Json 스트링 만들기 ====
파일 Uri를 인자로 하여 Json 스트링을 만드는 방법은 다음과 같다.
// 파일 내용 읽어서 String으로 만들기
fun LoadFileFromUri(uri: Uri?, cr : ContentResolver) : String {
var words : String = ""
if(uri==null) {
Log.e("LoadFileFromUri", "Unable to load the file")
} else {
val inputStream = cr.openInputStream(uri)
val reader = BufferedReader(InputStreamReader(inputStream))
var line = reader.readLine()
words += line + "\n"
while (line != null) {
Log.d("LoadFileFromUri", line)
line = reader.readLine()
words += line + "\n"
}
}
return words
}
==== 3. 파일피커로 Json 요소 읽는 전체 소스 ====
파일피커로 Json 파일을 읽는다면 다음과 같이 만들면 된다.
// 파일 픽커
val contentResolver = LocalContext.current.contentResolver
val result = remember { mutableStateOf(null) }
val predictions = remember { mutableStateOf("") }
val description = remember { mutableStateOf("") }
val main_text = remember { mutableStateOf("") }
val pickJsonFileLauncher = rememberLauncherForActivityResult(
ActivityResultContracts.OpenDocument())
{
result.value = it
notification.value = result.value.toString()
val json = LoadFileFromUri(uri = result.value, contentResolver)
// Json 문장에서 Json 요소 뽑아내기
try {
val jsonObject : JSONObject = JSONObject(json);
predictions.value = jsonObject.getString("predictions")
val jsonArray : JSONArray = JSONArray(predictions.value)
for (i in 0..jsonArray.length())
{
val subjsonObject : JSONObject = jsonArray.getJSONObject(i)
description.value += "description : " + subjsonObject.getString("description") + "\n" + "id : " + subjsonObject.getString("id") + "\n"
val structured_formatting : String = subjsonObject.getString("structured_formatting");
val subJsonObject2 : JSONObject = JSONObject(structured_formatting);
main_text.value += subJsonObject2.getString("main_text") + "\n"
}
} catch (e : JSONException) {
e.printStackTrace();
}
}