Kotlin 数据类 |添加我自己的变量而不是 JSON 键
Posted
技术标签:
【中文标题】Kotlin 数据类 |添加我自己的变量而不是 JSON 键【英文标题】:Kotlin data class | add my own variables other than JSON keys 【发布时间】:2018-11-04 11:07:58 【问题描述】:我正在为我的 andorid 应用程序使用改造和 kotlin。
对于我的一个 API,我有以下数据类
class Set(val set_id: Long, val tickets: List<Ticket>, val timer: Int)
class Ticket(val ticket_id: Long, val rows: List<Row>)
class Row(val row_id: Long, val row_numbers: List<Int>)
示例 JSON 数据
"set_id": 60942,
"tickets": [
"ticket_id": 304706,
"rows": [
"row_id": 914116,
"row_numbers": [
0,
11,
21,
0,
42,
52,
0,
76,
85
]
]
],
"timer": 12
Set
类包含Ticket
的列表,每张票都有Row
的列表
我的 JSON 对象只包含这些值,直到这里它都可以正常工作。改造映射也在起作用。
问题:
我想为Ticket
类添加我自己的布尔字段/变量isPlaying
,稍后将在应用程序中更新。但是,这个字段应该默认设置为true。
所以我试过了
class Ticket(val ticket_id: Long, val rows: List<Row>, var isPlaying: Boolean = true)
还有这个
class Ticket(val ticket_id: Long, val rows: List<Row>)
var isPlaying: Boolean = true
注意:JSON 没有 isPlaying
键,我只希望它用于应用逻辑。
两者都不起作用,isPlaying
总是显示false
。我希望它默认为true
。
请帮帮我。谢谢!
【问题讨论】:
如果您需要后期处理,您可以按照medium.com/@elye.project/…的建议将值设置为 true @Raghunandan 我去看看 【参考方案1】:由于下面使用的解析库,当对象通过改造实例化时,默认参数在数据类中不起作用,这可能会在不调用构造函数的情况下创建对象。例如Gson
使用sun.misc.Unsafe
来创建对象。
您可以做的是为具有默认值的字段添加支持属性:
class Ticket(
val ticket_id: Long,
val rows: List<Row>,
private var _isPlaying: Boolean? = true
)
var isPlaying
get() = _isPlaying ?: true
set(value)
_isPlaying = value
【讨论】:
接受!你很快。 澄清一下——Gson 不使用反射,它使用sun.misc.Unsafe
来减少反射开销。第二件事作者提到属性应该稍后更新,这是只读属性不可能的,可能应该从val
更改为var
@hluhovskyi 感谢您的澄清,我已经更新了我的答案
响应中是否需要 _isPlaying?
它是否也适用于 kotlin data class
?我试过但没有运气:(【参考方案2】:
问题的根源在于 GSON 创建对象不是通过构造函数调用,而是通过 Unsafe 人员。因此,它会导致诸如空安全或属性初始化之类的破坏。
我知道如何解决您的情况的唯一方法如下:
class Ticket(val ticket_id: Long, val rows: List<Row>)
private var _isPlaying: Boolean? = null
var isPlaying: Boolean
get() = _isPlaying ?: true // <-- default value
set(value)
_isPlaying = value
这里我们创建一个支持属性_isPlaying
,它将被 GSON 初始化为 null。接下来,我们为公共属性添加自定义 getter 和 setter,如果 _isPlaying
为空,它们会检查每个调用的方法。如果是这样,它会返回您的默认值。否则,它返回存储在_isPlaying
中的值
是的,它看起来很丑。否则,您应该考虑使用另一个 json 库,例如 Jackson,据我所知它很好地支持 Kotlin。
【讨论】:
非常感谢。解决方法起到了神奇的作用。但需要一些编辑。var isPlaying: Boolean
不是必需的
通过您建议的编辑,您可以公开可为空的字段,以防它真的没有。当然你可以使用field
关键字,但是你的模型公共界面会变得更加嘈杂。
是的,但是 android 会显示警告并建议将其更改为字段。
这只是 lint 警告,它不知道你的意图,显然你不应该到处遵循这样的警告。对我来说,创建清晰的商业模式比 Android lint 发出的警告要重要得多。
私有变量_isPlaying:布尔值? =空;保持它为空对我有用【参考方案3】:
使用 GsonBuilder setFeildNamePolicy
val gson = GsonBuilder()
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
.create()
val info = gson.fromJson(json, Account::class.java)
data class Account(
@SerializedName("user_name") var userName: String = "",
@SerializedName("ticket_id") var ticketId: String = "",
@SerializedName("row_id") var rowId: String = "")
【讨论】:
我没有得到这个,我不想手动将 json 字符串映射到对象。改造就可以了 在改造中你可以在改造初始化器中添加 .addConverterFactory(GsonConverterFactory.create(gson)) 我想你没有得到我的问题。我想将自己的变量添加到数据类中。 可以添加有问题的json数据吗 添加了示例 json 数据以上是关于Kotlin 数据类 |添加我自己的变量而不是 JSON 键的主要内容,如果未能解决你的问题,请参考以下文章
为啥 Kotlin 类默认是 final 而不是 open?
在 kotlin 中的 requestLocationUpdates 之后移动标记而不是添加它
Kotlin 类的 Android 单元测试因“找不到符号类...”而失败