bugfix> android > 投稿

私はandoridアプリにレトロフィットとkotlinを使用しています。

APIの1つについて、次のデータクラスがあります

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オブジェクトにはこれらの値のみが含まれており、ここまでは正常に機能しています。レトロフィットマッピングも機能しています。

問題: 独自のブールフィールド/変数 isPlaying を追加したいクラス Ticket の 、アプリで後で更新されます。ただし、このフィールドはデフォルトで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 になりたいデフォルトで。

私を助けてください。ありがとうございました!

回答 3 件
  • デフォルトの引数は、下で使用される解析ライブラリによりオブジェクトがレトロフィットでインスタンス化される場合、データクラスでは機能しません。おそらく、コンストラクターを呼び出さずにオブジェクトを作成します。たとえば、 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がコンストラクター呼び出しではなく、安全でないスタッフを介してオブジェクトを作成するという事実です。したがって、null-safetyまたはプロパティの初期化などの破損したものにつながります。

    あなたのケースを回避する方法を知っている唯一の方法は次のように見えます:

    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
            }
    }
    
    

    ここで、1つのバッキングプロパティ _isPlaying を作成します  GSONによってnullに初期化されます。次に、 _isPlaying の場合に呼び出されるそれぞれをチェックするパブリックプロパティのカスタムゲッターとセッターを追加します  無効である。もしそうなら、それはあなたのデフォルト値を返します。それ以外の場合は、 _isPlaying に格納されている値を返します

    はい、見苦しいです。そうでなければ、ジャクソンのような別のjsonライブラリの使用を検討する必要があります。これは私が知っているようにKotlinをよくサポートしています。

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

あなたの答え