Kotlin 反序列化任何不支持的类型

Posted

技术标签:

【中文标题】Kotlin 反序列化任何不支持的类型【英文标题】:Kotlin Deserialize Any Type Not Supported 【发布时间】:2019-03-28 07:45:58 【问题描述】:

我正在尝试使用 kotlin.serialization 将 JSON 反序列化为 kotlin 类。但是,当代码去反序列化 json 时,它会抛出错误 kotlinx.serialization.SerializationException: Any type is not supported

谁能帮我解决这个问题?

产品:

@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()
)

产品尺寸:

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

产品属性:

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()
)

产品类别:

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

产品图片:

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 = ""
)

并且关联的 json 在 pastebin here

【问题讨论】:

能否添加以下数据类:ProductDimensions、ProductCategory、ProductImage 和 ProductAttribute @Gomino 添加了代码 您能告诉我您使用的是哪个版本的 kotlin 和 kotlin.serialization? @Gomino 1.3 现在 【参考方案1】:

这是一个使用最新版本 Kotlin (1.3.0) 和序列化运行时 (0.9.0) 的有效 cloud9(只需运行 ./gradlew run)解决方案

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

请注意,某些属性必须添加 @Optional 注释才能使此序列化与您的示例一起使用,因此解析的非严格版本。

@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()
)

注意:date_createdstock_status

根据您的 json 原始数据生成数据类的一个很好的在线工具是quicktype.io

编辑:刚刚发现 cloud9 两年前被亚马逊收购了,你不能再创建一个帐户来查看公共工作区。 所以这里是link to the filesystem

【讨论】:

MutableMap怎么办?【参考方案2】:

我刚刚尝试过,但无法复制您的问题。您能否提供一个 github 存储库,以便我们可以看到问题所在?

您的 pastebin 链接中的 JSON 存在一个问题,即缺少 stock_status 值,所以我遇到了这个错误:kotlinx.serialization.MissingFieldException: Field stock_status is required, but it was missing

但是,一旦我将该值添加到 JSON 中,我就可以很好地对其进行反序列化。

这是我使用的代码:

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

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

另一件事是根据documentation

使用 Kotlin 序列化需要 Kotlin 编译器 1.3.0 或更高版本。

Kotlin 1.3 是最近才正式发布的,所以您是否可能使用发布候选版本之类的东西,而不是正式版本(它对我有用)?也许将所有依赖项更新到最新版本并重试?

【讨论】:

您的代码抛出错误“此声明是实验性的,必须用'@kotlinx.serialization.ImplicitReflectionSerializer'标记” 试试这个:val products = JSON(strictMode = false).parse(Product.serializer().list, File("./serializationTest.json").readText())

以上是关于Kotlin 反序列化任何不支持的类型的主要内容,如果未能解决你的问题,请参考以下文章

Kotlin中Json的序列化与反序列化 -- GsonMoshi

Kotlin中Json的序列化与反序列化 -- GsonMoshi

Kotlin中Json的序列化与反序列化 -- GsonMoshi

如何在Kotlin中用GSON实现多态列表反序列化?

Kotlin Gson反序列化

为什么kotlin jackson无法反序列化列表