当前位置: 首页 > 知识库问答 >
问题:

Moshi错误:@JSONClass不能应用于[class]。不得密封

顾斌
2023-03-14

想象一下这个数据示例

    "meta_data": [
                {
                    "id": 40097,
                    "key": "_wcf_frm_created",
                    "value": ""
                },
                {
                    "id": 40098,
                    "key": "_wcf_custom_degin_checkbox",
                    "value": ""
                },
                {
                    "id": 40099,
                    "key": "_wcf_frm_data",
                    "value": {
                        "1": {
                            "1": "",
                            "2": "",
                            "3": "chk_box"
                        }
                    }
                },
                {
                    "id": 40119,
                    "key": "_vendor_select",
                    "value": "6484"
                },
                {
                    "id": 40120,
                    "key": "_vendor_percentage",
                    "value": "1"
                },
                {
                    "id": 40121,
                    "key": "_vendor_pro_cat",
                    "value": "Accessories"
                }
            ]
sealed class Value {
        class StringMapMapValue(val value: Map<String, Map<String, String>>) : Value()
        class StringValue(val value: String)                                 : Value()
    }
    @JsonClass(generateAdapter = true)
    data class MetaDatum (
            val id: Long,
            val key: String,
            val value: Value
    )
    @JsonClass(generateAdapter = true)
    sealed class Value {
        class StringMapMapValue(val value: Map<String, Map<String, String>>) : Value()
        class StringValue(val value: String)                                 : Value()
    }

我想要注意的是,完整的json要比这个大得多。然而,这是我唯一的问题。我也有一些枚举问题,但可以用字符串替换

我收到的错误是error:@JSONClass不能应用于NET......activity.Value:必须不是密封的公共静态抽象类值

因此,我的问题是,如何使用多个枚举类型解码json。

enum Value: Codable {
    case string(String)
    case stringMapMap([String: [String: String]])
    
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        if let x = try? container.decode([String: [String: String]].self) {
            self = .stringMapMap(x)
            return
        }
        if let x = try? container.decode(String.self) {
            self = .string(x)
            return
        }
        throw DecodingError.typeMismatch(Value.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for Value"))
    }
    
    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        switch self {
        case .string(let x):
            try container.encode(x)
        case .stringMapMap(let x):
            try container.encode(x)
        }
    }
}

调用数据

fun retrieveMenu(sku: Int, SSLAuth: String)
    {

        doAsync {

            val client = OkHttpClient().newBuilder()
                .build()
            val formBody: RequestBody = FormBody.Builder()
                .build()
            val request: Request = Request.Builder()
                .url("https://carteapp.net/..................")
                .method("Get", formBody)
                .build()
            client.newCall(request).execute().use { response ->
                if (!response.isSuccessful) throw IOException("Unexpected code $response")

                val gist =
                        gistJsonAdapter.fromJson(response.body!!.source())
                println(gist)


            }
        }

    }

private val moshi = Moshi.Builder().build()
private val gistJsonAdapter = moshi.adapter(BarcodeScannerActivity.WcProductCall::class.java)
@JsonClass(generateAdapter = true)
    data class WcProductCall (
            val id: Long,
            ...........
            val metaData: List<MetaDatum>,
           ...
    )

共有1个答案

章玮
2023-03-14

这有点棘手,因为Moshi不允许密封/抽象类,我的想法是使用DTO模式(这是一种使用数据传输对象在单个网络请求中传递尽可能多的数据的模式)

创建一个包含两个/所有数据的数据类(您的DTO)

@JsonClass(generateAdapter = true)
data class MetaDatumDTO (
        val id: Long,
        val key: String,
        val value1: Value1DTO?,
        val value2: Value2DTO?
)

@JsonClass(generateAdapter = true)
data class Value1DTO(val value: Map<String, Map<String, String>>)

@JsonClass(generateAdapter = true)
data class Value2DTO(val value: String) 

然后在您的存储库/模型中,当您检索数据时,使用映射器函数将数据映射到您想要使用的数据类

data class MetaDatum(
    val id: Long,
    val key: String,
    val value: Value?
)

sealed class Value {
    data class Value1(val value: Map<String, Map<String, String>>) : Value()
    data class Value2(val value: String) : Value()
}

fun MetaDatumDto.mapFromNetworkRequest(): MetaDatum {
    return MetaDatum(
        id = id,
        key = key,
        value = getValueFromDTO()
    )
}

fun MetaDatumDto.getValueFromDTO(): Value? {
    return (value1 as? Value1) ?: (value2 as? Value2)
}
 类似资料:
  • 我在用Moshi注释设置我的领域实例时遇到了一个问题。还没有发现类似的问题。 下面的模型类 和收到的错误 提前感谢您的任何帮助:)

  • 我正在Android上使用Moshi 1.8.0,并按照Moshi文档中的说明创建自定义字段:https://github.com/square/Moshi#custom-field-names-with-json 这意味着我的请求数据类是这样的: 但问题是实际的HTTP请求是这样发送的: 我所期待的是我的请求是这样的: 这似乎对响应工作得很好,但我不知道如何使它对请求工作。 谢谢!这难道不是注释

  • 简而言之,我尝试使用Spring Security进行授权。但我犯了错误

  • 我试图用Moshi解析一个Json响应,我遇到的问题是键的值是字符串上的Json换行: 这是我的课

  • 我在我的项目分级文件中收到了这样的警告: 警告:(16,5)“生成类型”不能应用于“(groovy.lang.closure )” 我的buildTypes部分是: 我目前使用的是Android Studio 1.1.0、CompilesDKVersion22、BuildToolsVersion22.0.0和TargetSDKVersion22。我试着退让到21岁,但还是收到了警告。 是什么导致了

  • 问题内容: 我试图访问从Person类继承的Indicator类的变量。但是,我认为我没有正确地进行初始化。 我得到以下信息:’错误:实例成员’name’不能用于’Indicator’`类型。 问题答案: 您不能直接以静态方法访问非静态内容。 该方法是静态的,因为已使用修饰符对其进行了修改: 的属性不是静态的,因为它没有被修改。 由于非静态成员属于该类的每个单独实例,而静态成员属于该类本身,因此静