0

I have the following JSON data

[
{
"type": "carousal",
"items": [
  {
    "type": "story",
    "data": {
      "display_name": "grinning 1"
    }
  },
  {
    "type": "story",
    "data": {
      "display_name": "grinning 2"
    }
  }
]
},
{
"type": "carousal",
"items": [
  {
    "type": "story",
    "data": {
      "display_name": "grinning 3"
    }
  },
  {
    "type": "story",
    "data": {
      "display_name": "grinning 4"
    }
  }
]
}
]

Corresponding data classes are

data class ServerResponse(
@SerializedName("type")
val type: String,
@SerializedName("items")
val subTypes: List<ServerResponse>,
@SerializedName("data")
val data: Data)

data class Data(
@SerializedName("display_name")
val displayName: String)

This is the final data class I want the original object to be converted to

data class ConvertedData(val type: String, val name: String)

This is the kind of response I am looking for using map operator which returns a list convertedData object

[
  {
    "type": "story",
    "display_name": "grinning 1"
  },
  {
    "type": "story",
    "display_name": "grinning 2"
  },
  {
    "type": "story",
    "display_name": "grinning 3"
  },
  {
    "type": "story",
    "display_name": "grinning 4"
  }
]

I created an extension to convert the data as

fun ServerResponse.toConvertedData(): ConvertedData? {
val data: ConvertedData? = null
if(type.equals("carousal")){
    // compare subtypes type to "story" and put it converted data object
}
return data
}

The commented part I can't figure out since I need to go in the items array and want to use it as follows

val convertedData= serverResponse.map { it.toConvertedData() }
4
  • It would be nice if you could reindent the snippets properly Commented May 31, 2021 at 14:38
  • Have you checked the map function in the documentation? According to my understanding, this logic is incorrect. You will be reading a list of ServerResponse and returning a mapped list with ConvertedData items. Or You can do it one by one by iterating outside. But map function will help you do it. kotlinlang.org/docs/collection-transformations.html#map Commented May 31, 2021 at 15:02
  • It looks like your initial data model for the JSON is not really correct, unless the structure of the JSON is way more flexible than it appears to be Commented May 31, 2021 at 15:21
  • You seem to be trying to convert a single ServerResponse into a single ConvertedData instance. You need to get a list of ConvertedData from a ServerResponse if you want to get the desired output. Also, if you're only taking the ones with "story" subtype, why do you need to store a type in ConvertedData? Commented May 31, 2021 at 15:38

3 Answers 3

3

map is generally used when each source item is converted to one target item. If each item in the source list can yield multiple items in the target list, you should use flatMap instead.

In your case, a single ServerResponse instance can be mapped to multiple ConvertedData instances:

fun ServerResponse.convertSubTypes(): List<ConvertedData> = 
    subTypes
        .filter { it.type == "story" }
        .map { ConvertedData(type = it.type, name = it.data.displayName) }

Then you can use it with flatMap:

val serverResponseList = TODO("get list of server response from somewhere")
val result = serverResponseList.filter { it.type == "carousal" }
                               .flatMap { it.convertSubTypes() }
Sign up to request clarification or add additional context in comments.

Comments

0

You should have below classes

data class ConvertedData(val type: String, val name: String)

data class ServerResponse(val type: String, val items: List<Grining>)

data class Grining(val type:String, val data:Data)

data class Data(val display_name: String)

data class Response(val response: List<ServerResponse>)

Then try this function to convert it to required json format

fun Response.toConvertedData(): List<ConvertedData> {
val outputList: MutableList<ConvertedData> = mutableListOf()
this.response.forEach {  serverResponse ->
    if(serverResponse.type == "carousal"){
        // compare subtypes type to "story" and put it converted data object
            serverResponse.items.forEach {
                outputList.add(ConvertedData(it.type, it.data.display_name))
            }
        }
    }

    return outputList
}

Comments

0

Hey the logic you have used is not correct, map won't be useful for your use case since map used to convert each item to a target item. Also in your case your json is a list of ServerResonse class. use the extension function below, hope this will solve your problem

fun List<ServerResponse>.toConvertedData(): List<ConvertedData> {
    val convertedData:ArrayList<ConvertedData> = ArrayList()
    this.forEach {  data->
        if(data.type == "carousal"){
            data.subTypes.forEach { subData->
                if(subData.type == "story"){
                    convertedData.add(ConvertedData(subData.type,subData.data.displayName))
                }

            }
        }

    }
    return convertedData
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.