2017-12-29 6 views
2

parsed JSONをJSON::Anyタイプとしてカスタムオブジェクトにマッピングするにはどうすればよいですか?JSON :: AnyをCrystalオブジェクトのカスタムオブジェクトにマップする方法は?

私の場合、私はチャットクライアントに取り組んでいます。チャットAPIは、JSONと次のように要求に応答することができます

{"ok" => true, 
"result" => 
    [{"update_id" => 71058322, 
    "message" => 
    {"message_id" => 20, 
     "from" => "Benjamin", 
     "text" => "hey"}}]} 

どこか私のAPIクライアントコード内の私はいくつかの基本的な健康チェックを実行し、応答消費者に結果を渡すためにこれらのJSONを解析します。消費者には、私はresult以上の配列を反復処理し、適切なオブジェクトにそれぞれの更新を変換しよう:

module Types 
    class Update 
    JSON.mapping({ 
     update_id: {type: Int32}, 
     message: {type: Message}, 
    }) 
    end 
end 

module Types 
    class Message 
    JSON.mapping({ 
     message_id: Int32, 
     date:  Int32, 
     text:  String, 
    }) 
    end 
end 

return unless response["ok"] 
response["result"].each do |data| 
    update = Types::Update.from_json(data) 
end 

は残念ながら、最後の行は、コンパイルエラーになり:

no overload matches 'JSON::Lexer.new' with type JSON::Any 

どうやら、Object.from_jsonだけString JSONsを受け入れることができますJSONは解析されません。私の場合、dataJSON::Anyオブジェクトです。

ダーティフィックスTypes::Update.from_json(data.to_json)が動作しますが、それはうんざりです。

JSONオブジェクトをネストされた構造をすべて保持するカスタムタイプにマップする適切な方法は何ですか?

答えて

4

JSON.mappingは、JSON.parseと一緒にうまく動作しません。あなたが別のマッピングTypes::Resultを作成しても、はるかに便利で動作するようにしているObject.from_jsonを使用して穴JSONを解析することができ、あなたの問題を解決するには:

module Types 
    class Message 
    JSON.mapping(
     message_id: Int32, 
     text:  String 
    ) 
    end 

    class Update 
    JSON.mapping(
     update_id: Int32, 
     message: Message 
    ) 
    end 

    class Result 
    JSON.mapping(
     success: { key: "ok", type: Bool }, 
     updates: { key: "result", type: Array(Update) } 
    ) 
    end 
end 

result = Types::Result.from_json string_json 
result.success     # => true 
result.updates.first.message.text # => "hey" 
+0

は、Vitaliiをいただきありがとうございます、そのアプローチは働きました! – vtambourine

関連する問題