Skip to content

Instantly share code, notes, and snippets.

@delacrixmorgan
Last active February 4, 2019 01:58
Show Gist options
  • Save delacrixmorgan/fc3ac091bf7b8ac0ecdf1c477a5413c9 to your computer and use it in GitHub Desktop.
Save delacrixmorgan/fc3ac091bf7b8ac0ecdf1c477a5413c9 to your computer and use it in GitHub Desktop.
Kotlin Flattening Json API

Kotlin Flattening Json API

JSON that conform to the structure of https://jsonapi.org/. Flattening the JSON to able to deserialize into Kotlin objects later on.

data_post.json

{
  "data": [
    {
      "id": "3b30cf41-332d-4004-a3f1-e5397572f9c5",
      "type": "post",
      "attributes": {
        "title": "I think, therefore I am",
        "body": "Lorem ipsum dolor sit amet, veniam corrumpit id his. Id sapientem theophrastus duo. Eu tempor primis sea. Ius paulo zril homero te, verear constituto intellegebat vix in. Mandamus similique qui ei. Agam detraxit referrentur mei ei, choro volumus ad quo.",
        "createdAt": "2019-01-01T14:01:21Z"
      },
      "relationships": {
        "author": {
          "data": {
            "id": "dd82fe12-94b4-4323-94d7-e6216203dd33",
            "type": "user"
          }
        }
      }
    }
  ],
  "included": [
    {
      "type": "user",
      "id": "dd82fe12-94b4-4323-94d7-e6216203dd33",
      "attributes": {
        "firstName": "Robyn",
        "lastName": "Pollard"
      }
    }
  ]
}

PollInstrumentedTest.kt

@RunWith(AndroidJUnit4::class)
class PostInstrumentedTest {
    private val context: Context by lazy {
        InstrumentationRegistry.getInstrumentation().targetContext
    }

    @Test
    fun decodePostJson() {
        val inputStream = this.context.resources.openRawResource(R.raw.data_post)
        val responseObject = inputStream.bufferedReader().use(BufferedReader::readText)

        val dataJsonArray = JSONObject(responseObject).optJSONArray("data")
        val includedJsonArray = JSONObject(responseObject).optJSONArray("included")

        Assert.assertTrue("Post Data JSON is Empty", dataJsonArray.length() > 1)
        Assert.assertTrue("Post Included JSON is Empty", includedJsonArray.length() > 1)

        val postsJsonObject = arrayListOf<JSONObject>()

        (0 until dataJsonArray.length()).forEach {
            val postObject = dataJsonArray.optJSONObject(it)
            val postProcessedObject = JSONObject()

            postProcessedObject.put("id", postObject.optString("id"))
            postProcessedObject.put("objectType", postObject.optString("type"))

            postProcessedObject.putArray(postObject.optJSONObject("attributes"))
            postProcessedObject.putRelationshipObject(postObject.optJSONObject("relationships"), includedJsonArray)

            postsJsonObject.add(postProcessedObject)
        }

        Assert.assertTrue("Processing Post Data Not Tallying", postsJsonObject.size == dataJsonArray.length())
    }

    private fun JSONArray.findObject(id: String): JSONObject {
        (0 until this.length()).forEach {
            val findObject = this.optJSONObject(it)

            if (findObject.optString("id") == id) {
                return findObject
            }
        }
        return JSONObject()
    }

    private fun JSONObject.putArray(targetJson: JSONObject) {
        val keys = targetJson.keys()
        while (keys.hasNext()) {
            val key = keys.next()
            this.put(key, targetJson.opt(key))
        }
    }

    private fun JSONObject.putRelationshipObject(targetJson: JSONObject, includedJsonArray: JSONArray) {
        val keys = targetJson.keys()
        while (keys.hasNext()) {
            val key = keys.next()
            val attributesJsonObject = targetJson.optJSONObject(key).optJSONObject("data")
            val attributeId = attributesJsonObject.optString("id")
            val attributeType = attributesJsonObject.optString("type")

            val includedJsonObject = includedJsonArray.findObject(attributeId)
            val processedJson = JSONObject()

            processedJson.put("id", attributeId)
            processedJson.put("type", attributeType)
            processedJson.putArray(includedJsonObject.optJSONObject("attributes"))

            this.put(key, processedJson)
        }
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment