I am trying to store BigDecimal in Firebase:
我正在尝试在Firebase中存储BigDecimal:
data class Money(val amount: BigDecimal = BigDecimal.ZERO, val currency: Currency = Currency.USD)
But when pushing data to database, getting an exception:
但当将数据推送到数据库时,会出现异常:
com.google.firebase.database.DatabaseException: Failed to parse node with class class java.math.BigDecimal
at com.google.android.gms.internal.zzbpf.zza(Unknown Source)
at com.google.android.gms.internal.zzbpf.zzar(Unknown Source)
at com.google.android.gms.internal.zzbpf.zza(Unknown Source)
at com.google.android.gms.internal.zzbpf.zzar(Unknown Source)
at com.google.android.gms.internal.zzbpf.zza(Unknown Source)
at com.google.firebase.database.DatabaseReference.zza(Unknown Source)
at com.google.firebase.database.DatabaseReference.setValue(Unknown Source)
How can I store it?
我怎么能储存它?
1 个解决方案
#1
1
You can create a following delegate:
您可以创建以下委托:
class BigDecimalConverterDelegate(val bigDecimalProperty: KMutableProperty<BigDecimal>) {
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
return bigDecimalProperty.getter.call().toString()
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
bigDecimalProperty.setter.call(BigDecimal(value))
}
}
Then you have to create two properties:
然后必须创建两个属性:
data class Money(
@get:Exclude @set:Exclude var bigDecimalAmount: BigDecimal = BigDecimal.ZERO
) {
var amount: String by BigDecimalConverterDelegate(this::bigDecimalAmount)
}
First BigDecimal
property is annotated with @get:Exclude
and @set:Exclude
so it will be ignored by Firebase during serialization/deserialization.
第一个BigDecimal属性使用@get注释:排除和@set:排除,在序列化/反序列化期间,它将被Firebase忽略。
The String
property uses the delegate defined above. It doesn't have a backing field so Firebase will use String getAmount()
and setAmount(String amount)
methods while serializing/deserializing this class. These calls will be delegated to the BigDecimalConverterDelegate
which will set or get the value directly from the BigDecimal
property.
String属性使用上面定义的委托。它没有支持字段,所以Firebase在序列化/反序列化这个类时将使用字符串getAmount()和setAmount(String amount)方法。这些调用将被委托给BigDecimalConverterDelegate,后者将直接从BigDecimal属性设置或获取值。
Please note that you also have to include the kotlin-reflect
lib:
请注意,您还必须包括kotlin-反射lib:
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
Issue with kotlin-noarg
Unfortunately delegates don't work if you would want to use them with "kotlin-noarg" plugin (https://youtrack.jetbrains.com/issue/KT-16692). The empty constructor is totally empty and delegates are not initialized there:
不幸的是,如果您想使用“kotlin-noarg”插件(https://youtrack.jetbrains.com/issue/KT-16692),委托就不能工作。空的构造函数是完全空的,并且委托在那里没有初始化:
public Money(@NotNull BigDecimal bigDecimalAmount) {
Intrinsics.checkParameterIsNotNull(bigDecimalAmount, "bigDecimalAmount");
super();
this.bigDecimalAmount = bigDecimalAmount;
this.amount$delegate = new BigDecimalConverterDelegate((KMutableProperty)(new Money$amount$2(this)));
}
public Money() {
}
#1
1
You can create a following delegate:
您可以创建以下委托:
class BigDecimalConverterDelegate(val bigDecimalProperty: KMutableProperty<BigDecimal>) {
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
return bigDecimalProperty.getter.call().toString()
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
bigDecimalProperty.setter.call(BigDecimal(value))
}
}
Then you have to create two properties:
然后必须创建两个属性:
data class Money(
@get:Exclude @set:Exclude var bigDecimalAmount: BigDecimal = BigDecimal.ZERO
) {
var amount: String by BigDecimalConverterDelegate(this::bigDecimalAmount)
}
First BigDecimal
property is annotated with @get:Exclude
and @set:Exclude
so it will be ignored by Firebase during serialization/deserialization.
第一个BigDecimal属性使用@get注释:排除和@set:排除,在序列化/反序列化期间,它将被Firebase忽略。
The String
property uses the delegate defined above. It doesn't have a backing field so Firebase will use String getAmount()
and setAmount(String amount)
methods while serializing/deserializing this class. These calls will be delegated to the BigDecimalConverterDelegate
which will set or get the value directly from the BigDecimal
property.
String属性使用上面定义的委托。它没有支持字段,所以Firebase在序列化/反序列化这个类时将使用字符串getAmount()和setAmount(String amount)方法。这些调用将被委托给BigDecimalConverterDelegate,后者将直接从BigDecimal属性设置或获取值。
Please note that you also have to include the kotlin-reflect
lib:
请注意,您还必须包括kotlin-反射lib:
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
Issue with kotlin-noarg
Unfortunately delegates don't work if you would want to use them with "kotlin-noarg" plugin (https://youtrack.jetbrains.com/issue/KT-16692). The empty constructor is totally empty and delegates are not initialized there:
不幸的是,如果您想使用“kotlin-noarg”插件(https://youtrack.jetbrains.com/issue/KT-16692),委托就不能工作。空的构造函数是完全空的,并且委托在那里没有初始化:
public Money(@NotNull BigDecimal bigDecimalAmount) {
Intrinsics.checkParameterIsNotNull(bigDecimalAmount, "bigDecimalAmount");
super();
this.bigDecimalAmount = bigDecimalAmount;
this.amount$delegate = new BigDecimalConverterDelegate((KMutableProperty)(new Money$amount$2(this)));
}
public Money() {
}