목차

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