如何在Firebase中存储BigDecimal ?

时间:2021-02-03 20:07:07

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