在Ruby中不使用OpenStruct将JSON反序列化为自定义对象

在Ruby中不使用OpenStruct将JSON反序列化为自定义对象,json,ruby,Json,Ruby,如何反序列化如下所示的JSON对象(来自真实Wells Fargo API响应的测试数据): 与其他自定义嵌套对象(帐户和事务)一起放入自定义ruby对象中?我见过很多人使用OpenStruct,但我不想使用OpenStruct。我想自己构建对象,并使用object\u class将其传递给JSON解析器 这篇文章让我走上了一条道路: 但我不想先创建对象,然后将其转换为JSON来解析它。我想从JSON直接转到自定义对象。有人知道如何不用OpenStruct来实现这一点吗?我仔细研究了一下,寻找

如何反序列化如下所示的JSON对象(来自真实Wells Fargo API响应的测试数据):

与其他自定义嵌套对象(帐户和事务)一起放入自定义ruby对象中?我见过很多人使用OpenStruct,但我不想使用OpenStruct。我想自己构建对象,并使用
object\u class
将其传递给JSON解析器

这篇文章让我走上了一条道路:


但我不想先创建对象,然后将其转换为JSON来解析它。我想从JSON直接转到自定义对象。有人知道如何不用OpenStruct来实现这一点吗?

我仔细研究了一下,寻找答案,每个人都使用OpenStruct来实现对象的反序列化。然而,JSON.parse函数有一个
object\u类
属性,我被确定可以做我想做的事情,最后。。。我是对的。使用此语法:

tc=JSON.parse(data.to_JSON,object_类:TransactionDetail::Collection,create_additions:true)
您可以打开数据对象(来自实际Wells Fargo API响应的测试数据):

使用嵌套的自定义对象插入以下自定义对象

> tc
#<TransactionDetail::Collection:0x00007fa690053708 @data={
"json_class"=>"TransactionDetail::Collection", 
:accounts=>{23784275367=>
#<TransactionDetail::Account:0x00007fa690053f50 
@json_class="TransactionDetail::Collection", 
@bank_id="091000019", @account_number="23784275367", 
@account_type="DEMAND_DEPOSIT", @account_name="QUALITY LIFE MUSSMAN CO", 
@currency_code="USD", @transaction_count=10, @transactions=[
#<TransactionDetail::Transaction:0x00007fa69004b918 
@json_class="TransactionDetail::Collection", @posting_date="2019-06-04", 
@value_date="2019-06-04", @transaction_datetime="2019-06-04 03:12:00Z", 
@debit_credit_indicator="DEBIT", @transaction_type="CHECK", 
@bai_type_code="045", @transaction_description="BANK ORIGINATED DEBIT FR 0000007186 THE SHERWIN-WILLIAMS COMPANY SUB ACCT 000004944938950", 
@transaction_amount=224.43, @zero_day_float=0, @one_day_float=0, 
@two_date_float=0, @check_number="0000", 
@bank_reference="082300000022", @transaction_status="POSTED">, 
#<TransactionDetail::Transaction:0x00007fa690049ca8 
@json_class="TransactionDetail::Collection", @posting_date="2019-06-04", 
@value_date="2019-06-04", @transaction_datetime="2019-06-04 02:12:00Z", 
@debit_credit_indicator="DEBIT", @transaction_type="CHECK", 
@bai_type_code="045", @transaction_description="BANK ORIGINATED DEBIT FR 0000007186 THE SHERWIN-WILLIAMS COMPANY SUB ACCT 000004944938950", 
@transaction_amount=224.43, @zero_day_float=0, @one_day_float=0, 
@two_date_float=0, @check_number="0000", 
@bank_reference="082300000022", @transaction_status="POSTED">, 
#<TransactionDetail::Transaction:0x00007fa69004f298 
@json_class="TransactionDetail::Collection", @posting_date="2019-06-04", 
@value_date="2019-06-04", @transaction_datetime="2019-06-04 01:12:00Z", 
@debit_credit_indicator="DEBIT", @transaction_type="CHECK", 
@bai_type_code="045", @transaction_description="BANK ORIGINATED DEBIT FR 0000007186 THE SHERWIN-WILLIAMS COMPANY SUB ACCT 000004944938950", 
@transaction_amount=224.43, @zero_day_float=0, @one_day_float=0, 
@two_date_float=0, @check_number="0000", 
@bank_reference="082300000022", @transaction_status="POSTED">, 
#<TransactionDetail::Transaction:0x00007fa69004e028 
@json_class="TransactionDetail::Collection", @posting_date="2019-06-03", 
@value_date="2019-06-03", @transaction_datetime="2019-06-03 16:18:20Z", 
@debit_credit_indicator="DEBIT", @transaction_type="CHECK", 
@bai_type_code="045", @transaction_description="BANK ORIGINATED DEBIT FR 0000007186 THE SHERWIN-WILLIAMS COMPANY SUB ACCT 000004944938950", @transaction_amount=224.43, 
@zero_day_float=0, @one_day_float=0, @two_date_float=0, 
@check_number="0000", @bank_reference="082300000022", 
@transaction_status="POSTED">, 
#<TransactionDetail::Transaction:0x00007fa69004cde0 
@json_class="TransactionDetail::Collection", @posting_date="2019-06-02", 
@value_date="2019-06-02", @transaction_datetime="2019-06-02 16:18:20Z", 
@debit_credit_indicator="DEBIT", @transaction_type="CHECK", 
@bai_type_code="045", @transaction_description="BANK ORIGINATED DEBIT FR 0000007186 THE SHERWIN-WILLIAMS COMPANY SUB ACCT 000004944938950", 
@transaction_amount=244.55, @zero_day_float=0, @one_day_float=0, 
@two_date_float=0, @check_number="0000", 
@bank_reference="082300000022", @transaction_status="POSTED">]>}, :account_array=>[23784275367]}>
object\u类
属性的文档记录很差,但工作正常。JSON解析器的纯ruby版本的源代码在如何使用此属性方面取得了突破

诀窍在于理解
object\u类
只是告诉解析器在解析JSON结构时“遇到”对象时该怎么做。否则,它将愉快地解析它知道如何处理的字符串、布尔和类型。如果您想返回一个特定的对象,那么必须告诉解析器在
json\u create
函数中要做什么。如果设置了所有必需的属性:

1) object_类必须用一个包含
JSON.create_id=>self.class.name
的哈希来初始化(这是解析器查找的第一件事,然后实例化这个类的一个空实例来开始构建),这在我的集合类的initialize方法中显示

2) 必须同时通过
object\u类
create\u additions:true
JSON.parse方法

3) 这方面不是100%确定,但我相信您需要
json\u createable?
object\u类中返回true

当解析器在JSON结构中看到一个对象时,它将解析工作交给
JSON\u create
函数,并遍历嵌套结构


在我的
json\u create
方法中,我选择了一些我知道会出现在json响应中的键,如果我检测到这些键,我将构建相应的对象并将其返回给解析器。解析器知道该对象在嵌套结构中的位置,并将其整齐地放置在那里。最后一步是返回
object\u类本身,由
new(o)
行完成。你可以像我一样,在你的
object\u类中做一些最后的重新组织,例如,我给所有帐户按帐号进行哈希查找,并添加了一个只有帐号的数组。

我投票将这个问题作为主题外的问题来结束,因为这不是一个问题。我建议阅读,最重要的是,查看Dry::Struct。我90%确信你可以达到同样的效果,但是代码是干净的,不包含不必要的硬编码细节。代价是它是另一种依赖。你能详细说明一下代码中哪些地方不“干净”吗?硬编码的细节是绝对必要的,我正在处理文本,并试图确定基于文本创建什么类型的对象。已知的钥匙是唯一可以关闭钥匙的东西。我将查看dry struct,但添加另一个依赖项的想法让我感到畏缩。“硬编码的细节是绝对必要的”-不,实际上不是。你的收藏是同质的。Accounts数组仅包含帐户。而且一个账户有许多交易(同样,没有任何账户混入)。如果您真的想使用同一个类来反序列化这两种类型,那么您必须对属性进行某种类型的切换,是的。但是为什么不使用单独的类呢?您的数据不是完全任意的形状。您知道您有一个顶级数组
帐户
。为什么不利用事实/知识呢?您的建议没有考虑对象类属性的工作方式。您只能传递一个类,不能传递多个类。
data = {
  "accounts": [
    {
      "bank_id": "091000019",
      "account_number": "23784275367",
      "account_type": "DEMAND_DEPOSIT",
      "account_name": "QUALITY LIFE MUSSMAN CO",
      "currency_code": "USD",
      "transaction_count": 5,
      "transactions": [
        {
          "posting_date": "2019-06-04",
          "value_date": "2019-06-04",
          "transaction_datetime": "2019-06-04 03:12:00Z",
          "debit_credit_indicator": "DEBIT",
          "transaction_type": "CHECK",
          "bai_type_code": "045",
          "transaction_description": "BANK ORIGINATED DEBIT FR 0000007186 THE SHERWIN-WILLIAMS COMPANY SUB ACCT 000004944938950",
          "transaction_amount": 224.43,
          "zero_day_float": 0,
          "one_day_float": 0,
          "two_date_float": 0,
          "check_number": "0000",
          "bank_reference": "082300000022",
          "transaction_status": "POSTED"
        },
        {
          "posting_date": "2019-06-04",
          "value_date": "2019-06-04",
          "transaction_datetime": "2019-06-04 02:12:00Z",
          "debit_credit_indicator": "DEBIT",
          "transaction_type": "CHECK",
          "bai_type_code": "045",
          "transaction_description": "BANK ORIGINATED DEBIT FR 0000007186 THE SHERWIN-WILLIAMS COMPANY SUB ACCT 000004944938950",
          "transaction_amount": 224.43,
          "zero_day_float": 0,
          "one_day_float": 0,
          "two_date_float": 0,
          "check_number": "0000",
          "bank_reference": "082300000022",
          "transaction_status": "POSTED"
        },
        {
          "posting_date": "2019-06-04",
          "value_date": "2019-06-04",
          "transaction_datetime": "2019-06-04 01:12:00Z",
          "debit_credit_indicator": "DEBIT",
          "transaction_type": "CHECK",
          "bai_type_code": "045",
          "transaction_description": "BANK ORIGINATED DEBIT FR 0000007186 THE SHERWIN-WILLIAMS COMPANY SUB ACCT 000004944938950",
          "transaction_amount": 224.43,
          "zero_day_float": 0,
          "one_day_float": 0,
          "two_date_float": 0,
          "check_number": "0000",
          "bank_reference": "082300000022",
          "transaction_status": "POSTED"
        },
        {
          "posting_date": "2019-06-03",
          "value_date": "2019-06-03",
          "transaction_datetime": "2019-06-03 16:18:20Z",
          "debit_credit_indicator": "DEBIT",
          "transaction_type": "CHECK",
          "bai_type_code": "045",
          "transaction_description": "BANK ORIGINATED DEBIT FR 0000007186 THE SHERWIN-WILLIAMS COMPANY SUB ACCT 000004944938950",
          "transaction_amount": 224.43,
          "zero_day_float": 0,
          "one_day_float": 0,
          "two_date_float": 0,
          "check_number": "0000",
          "bank_reference": "082300000022",
          "transaction_status": "POSTED"
        },
        {
          "posting_date": "2019-06-02",
          "value_date": "2019-06-02",
          "transaction_datetime": "2019-06-02 16:18:20Z",
          "debit_credit_indicator": "DEBIT",
          "transaction_type": "CHECK",
          "bai_type_code": "045",
          "transaction_description": "BANK ORIGINATED DEBIT FR 0000007186 THE SHERWIN-WILLIAMS COMPANY SUB ACCT 000004944938950",
          "transaction_amount": 244.55,
          "zero_day_float": 0,
          "one_day_float": 0,
          "two_date_float": 0,
          "check_number": "0000",
          "bank_reference": "082300000022",
          "transaction_status": "POSTED"
        }
      ]
    }
  ]
}
> tc
#<TransactionDetail::Collection:0x00007fa690053708 @data={
"json_class"=>"TransactionDetail::Collection", 
:accounts=>{23784275367=>
#<TransactionDetail::Account:0x00007fa690053f50 
@json_class="TransactionDetail::Collection", 
@bank_id="091000019", @account_number="23784275367", 
@account_type="DEMAND_DEPOSIT", @account_name="QUALITY LIFE MUSSMAN CO", 
@currency_code="USD", @transaction_count=10, @transactions=[
#<TransactionDetail::Transaction:0x00007fa69004b918 
@json_class="TransactionDetail::Collection", @posting_date="2019-06-04", 
@value_date="2019-06-04", @transaction_datetime="2019-06-04 03:12:00Z", 
@debit_credit_indicator="DEBIT", @transaction_type="CHECK", 
@bai_type_code="045", @transaction_description="BANK ORIGINATED DEBIT FR 0000007186 THE SHERWIN-WILLIAMS COMPANY SUB ACCT 000004944938950", 
@transaction_amount=224.43, @zero_day_float=0, @one_day_float=0, 
@two_date_float=0, @check_number="0000", 
@bank_reference="082300000022", @transaction_status="POSTED">, 
#<TransactionDetail::Transaction:0x00007fa690049ca8 
@json_class="TransactionDetail::Collection", @posting_date="2019-06-04", 
@value_date="2019-06-04", @transaction_datetime="2019-06-04 02:12:00Z", 
@debit_credit_indicator="DEBIT", @transaction_type="CHECK", 
@bai_type_code="045", @transaction_description="BANK ORIGINATED DEBIT FR 0000007186 THE SHERWIN-WILLIAMS COMPANY SUB ACCT 000004944938950", 
@transaction_amount=224.43, @zero_day_float=0, @one_day_float=0, 
@two_date_float=0, @check_number="0000", 
@bank_reference="082300000022", @transaction_status="POSTED">, 
#<TransactionDetail::Transaction:0x00007fa69004f298 
@json_class="TransactionDetail::Collection", @posting_date="2019-06-04", 
@value_date="2019-06-04", @transaction_datetime="2019-06-04 01:12:00Z", 
@debit_credit_indicator="DEBIT", @transaction_type="CHECK", 
@bai_type_code="045", @transaction_description="BANK ORIGINATED DEBIT FR 0000007186 THE SHERWIN-WILLIAMS COMPANY SUB ACCT 000004944938950", 
@transaction_amount=224.43, @zero_day_float=0, @one_day_float=0, 
@two_date_float=0, @check_number="0000", 
@bank_reference="082300000022", @transaction_status="POSTED">, 
#<TransactionDetail::Transaction:0x00007fa69004e028 
@json_class="TransactionDetail::Collection", @posting_date="2019-06-03", 
@value_date="2019-06-03", @transaction_datetime="2019-06-03 16:18:20Z", 
@debit_credit_indicator="DEBIT", @transaction_type="CHECK", 
@bai_type_code="045", @transaction_description="BANK ORIGINATED DEBIT FR 0000007186 THE SHERWIN-WILLIAMS COMPANY SUB ACCT 000004944938950", @transaction_amount=224.43, 
@zero_day_float=0, @one_day_float=0, @two_date_float=0, 
@check_number="0000", @bank_reference="082300000022", 
@transaction_status="POSTED">, 
#<TransactionDetail::Transaction:0x00007fa69004cde0 
@json_class="TransactionDetail::Collection", @posting_date="2019-06-02", 
@value_date="2019-06-02", @transaction_datetime="2019-06-02 16:18:20Z", 
@debit_credit_indicator="DEBIT", @transaction_type="CHECK", 
@bai_type_code="045", @transaction_description="BANK ORIGINATED DEBIT FR 0000007186 THE SHERWIN-WILLIAMS COMPANY SUB ACCT 000004944938950", 
@transaction_amount=244.55, @zero_day_float=0, @one_day_float=0, 
@two_date_float=0, @check_number="0000", 
@bank_reference="082300000022", @transaction_status="POSTED">]>}, :account_array=>[23784275367]}>