===== 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(); } }