2

I am trying to deserialize a JSON into a kotlin class using kotlin.serialization. However when the code goes to deserialize the json it throws the error kotlinx.serialization.SerializationException: Any type is not supported

Can anyone help me resolves this?

Product:

@Serializable
data class Product(
        val id: Int = 0,
        val name: String = "",
        val slug: String = "",
        val permalink: String = "",
        @SerialName("date_created") val dateCreated: String = "",
        @SerialName("date_created_gmt") val dateCreatedGmt: String = "",
        @SerialName("date_modified") val dateModified: String = "",
        @SerialName("date_modified_gmt") val dateModifiedGmt: String = "",
        val type: String = "",
        val status: String = "",
        val featured: Boolean = false,
        @SerialName("catalog_visibility") val catalogVisibility: String = "",
        val description: String = "",
        @SerialName("short_description") val shortDescription: String = "",
        val sku: String = "",
        val price: String = "",
        @SerialName("regular_price") val regularPrice: String = "",
        @SerialName("sale_price") val salePrice: String = "",
        @SerialName("on_sale") val onSale: Boolean = false,
        val purchasable: Boolean = false,
        @SerialName("total_sales") val totalSales: Int = 0,
        @SerialName("external_url") val externalUrl: String = "",
        @SerialName("tax_status") val taxStatus: String = "",
        @SerialName("tax_class") val taxClass: String = "",
        @SerialName("stock_quantity") val stockQuantity: String = "",
        @SerialName("stock_status") val stockStatus: String = "",
        val backorders: String = "",
        @SerialName("backorders_allowed") val backordersAllowed: Boolean = false,
        val backordered: Boolean = false,
        @SerialName("sold_individually") val soldIndividually: Boolean = false,
        val weight: String = "",
        val dimensions: ProductDimensions = ProductDimensions(),
        @SerialName("shipping_required") val shippingRequired: Boolean = false,
        @SerialName("shipping_taxable") val shippingTaxable: Boolean = false,
        @SerialName("shipping_class") val shippingClass: String = "",
        @SerialName("shipping_class_id") val shippingClassId: Int = 0,
        @SerialName("reviews_allowed") val reviewsAllowed: Boolean = false,
        @SerialName("average_rating") val averageRating: String = "",
        @SerialName("rating_count") val ratingCount: Int = 0,
        @SerialName("related_ids") val relatedIds: List<Int> = listOf(),
        @SerialName("upsell_ids") val upsellIds: List<Int> = listOf(),
        @SerialName("cross_sell_ids") val crossSellIds: List<Int> = listOf(),
        @SerialName("parent_id") val parentId: Int = 0,
        @SerialName("purchase_note") val purchaseNote: String = "",
        val categories: List<ProductCategory> = listOf(),
        val images: List<ProductImage> = listOf(),
        val attributes: List<ProductAttribute> = listOf(),
        val variations: List<Int> = listOf()
)

ProductDimension:

data class ProductDimensions(
        val length: String = "",
        val width: String = "",
        val height: String = ""
)

Product Attribute:

data class ProductAttribute(
        val id: Int = 0,
        val name: String = "",
        val position: Int = 0,
        val visible: Boolean = false,
        val variation: Boolean = false,
        val options: List<String> = listOf()
)

Product Category:

data class ProductCategory(
        val id: Int = 0,
        val name: String = "",
        val slug: String = ""
)

Product Image:

data class ProductImage(
        val id: Int = 0,
        @SerialName("date_created") val dateCreated: String = "",
        @SerialName("date_created_gmt") val dateCreatedGmt: String = "",
        @SerialName("date_modified") val dateModified: String = "",
        @SerialName("date_modified_gmt") val dateModifiedGmt: String = "",
        val src: String = "",
        val name: String = "",
        val alt: String = ""
)

And the associated json is on pastebin here

Adrian Le Roy Devezin
  • 672
  • 1
  • 13
  • 41

2 Answers2

4

Here is a working cloud9 (simply run ./gradlew run) solution using the last version of Kotlin (1.3.0) and the serialization runtime (0.9.0)

val serializer = Product.serializer().list
val json = JSON.nonstrict.parse<List<Product>>(serializer, jsonString)

Note that some attributes had to have the @Optional annotation added for this serialization to work with your sample, hence the nonstrict version of the parsing.

@Serializable
data class Product(
        val id: Int = 0,
        val name: String = "",
        val slug: String = "",
        val permalink: String = "",
        @Optional @SerialName("date_created") val dateCreated: String = "",
        @SerialName("date_created_gmt") val dateCreatedGmt: String = "",
        @SerialName("date_modified") val dateModified: String = "",
        @SerialName("date_modified_gmt") val dateModifiedGmt: String = "",
        val type: String = "",
        val status: String = "",
        val featured: Boolean = false,
        @SerialName("catalog_visibility") val catalogVisibility: String = "",
        val description: String = "",
        @SerialName("short_description") val shortDescription: String = "",
        val sku: String = "",
        val price: String = "",
        @SerialName("regular_price") val regularPrice: String = "",
        @SerialName("sale_price") val salePrice: String = "",
        @SerialName("on_sale") val onSale: Boolean = false,
        val purchasable: Boolean = false,
        @SerialName("total_sales") val totalSales: Int = 0,
        @SerialName("external_url") val externalUrl: String = "",
        @SerialName("tax_status") val taxStatus: String = "",
        @SerialName("tax_class") val taxClass: String = "",
        @SerialName("stock_quantity") val stockQuantity: String = "",
        @Optional @SerialName("stock_status") val stockStatus: String = "",
        val backorders: String = "",
        @SerialName("backorders_allowed") val backordersAllowed: Boolean = false,
        val backordered: Boolean = false,
        @SerialName("sold_individually") val soldIndividually: Boolean = false,
        val weight: String = "",
        val dimensions: ProductDimensions = ProductDimensions(),
        @SerialName("shipping_required") val shippingRequired: Boolean = false,
        @SerialName("shipping_taxable") val shippingTaxable: Boolean = false,
        @SerialName("shipping_class") val shippingClass: String = "",
        @SerialName("shipping_class_id") val shippingClassId: Int = 0,
        @SerialName("reviews_allowed") val reviewsAllowed: Boolean = false,
        @SerialName("average_rating") val averageRating: String = "",
        @SerialName("rating_count") val ratingCount: Int = 0,
        @SerialName("related_ids") val relatedIds: List<Int> = listOf(),
        @SerialName("upsell_ids") val upsellIds: List<Int> = listOf(),
        @SerialName("cross_sell_ids") val crossSellIds: List<Int> = listOf(),
        @SerialName("parent_id") val parentId: Int = 0,
        @SerialName("purchase_note") val purchaseNote: String = "",

        val categories: List<ProductCategory> = listOf(),
        val images: List<ProductImage> = listOf(),
        val attributes: List<ProductAttribute> = listOf(),
        val variations: List<Int> = listOf()
)

Notice: date_created, stock_status

A good online tool to generate your data class based on your json raw data is quicktype.io

Edit: Just figured out that cloud9 had been acquired by amazon two years ago, and you can no longer create an account to see public workspace. So here is the link to the filesystem

Gomino
  • 12,127
  • 4
  • 40
  • 49
0

I've just tried this and couldn't replicate your problem. Can you maybe provide a github repo where we can see the problem?

There was one issue in the JSON in your pastebin link, which was that the stock_status value was missing, so I hit this error: kotlinx.serialization.MissingFieldException: Field stock_status is required, but it was missing

However once I added that value into the JSON I could deserialize it fine.

Here's the code I used:

import kotlinx.serialization.*
import kotlinx.serialization.json.JSON
import java.io.File

val product = JSON(strictMode = false).parseList<Product>(File("./serializationTest.json").readText())

The other thing is that according to the documentation

Using Kotlin Serialization requires Kotlin compiler 1.3.0 or higher.

Kotlin 1.3 was only officially released very recently, so are you maybe using a release candidate or something, instead of the formal release (with which it worked for me)? Maybe update all your dependencies to the latest versions and try again?

Yoni Gibbs
  • 6,518
  • 2
  • 24
  • 37
  • 1
    Your code throws an error "this declaration is experimental and must be marked with '@kotlinx.serialization.ImplicitReflectionSerializer'" – Adrian Le Roy Devezin Oct 30 '18 at 14:04
  • Try this instead: `val products = JSON(strictMode = false).parse(Product.serializer().list, File("./serializationTest.json").readText())` – Yoni Gibbs Oct 30 '18 at 15:24