【问题标题】:Ruby serialization data structureRuby序列化数据结构
【发布时间】:2014-09-07 09:10:45
【问题描述】:

我正在尝试从 Ruby 序列化复杂的 JSON 结构。我没有使用 Rails,但我对 Ruby 足够陌生,所以我不确定这在这里是否重要。 另一端的 API 期待这样的东西

{ "command" : {
   "param" : { "field" : "val", "otherField":"otherVal" },
   "param" : { "field" : "val", "otherField":"otherVal" },
   "param" : { "field" : "val", "otherField":"otherVal" }
    }
}

在序列化之前,命令持有什么样的 ruby​​ 对象?它不是一个数组,因为会有另一层方括号(参见下面的示例)。而且我是 ruby​​ 的新手,但不要认为你可以在哈希中拥有多个具有相同名称的对象。

背景故事:因为哈希和数组在 Ruby 中非常好地序列化为 json,所以我期待这样的事情:

Ary = Array.new
Ary.push (param.new)
Ary.push (param.new)
Ary.push (param.new)
wrappedCmd = { "command" => Ary }
Oj.dump(wrappedCmd)

但这会产生:

{ "command" : [
   "param" : { "field" : "val", "otherField":"otherVal" },
   "param" : { "field" : "val", "otherField":"otherVal" },
   "param" : { "field" : "val", "otherField":"otherVal" }
    ]
}

我已经确认第一种格式是预期的,因为手动构建的序列化会通过,而第二种会产生无效的格式错误。

【问题讨论】:

  • 如果所有的键字面上都是“参数”,那么这就是 语义无效 JSON - 如果 API 是它想要的,那么它就会被破坏。在 Map(例如 JSON 对象或 Ruby 哈希)中无法复制键。确保所说的无效 JSON 确实是“正确的”。 (并且没有合适的 JSON 库允许发出这种损坏的标记。)
  • 嗯。好的。对 API 端没有任何控制权,它接受第一种格式。谢谢。

标签: ruby json serialization


【解决方案1】:

区别在于第一个包含哈希,第二个包含一个数组。所以你应该这样做:

cmd = {}
cmd['param1'] = Param.new
cmd['param2'] = Param.new
cmd['param3'] = Param.new
Oj.dump("command" => cmd)

确实,哈希不能有重复的键名。听起来您的 API 没有使用正确的 JSON?

【讨论】:

  • 但这不会产生:{ "command": param1: stuff, param2: stuff, param3: stuff }
  • 当然不是。至少,不是标准的 JSON 序列化器。
【解决方案2】:

如果您尝试解析该初始 JSON 字符串,会发生以下情况:

require 'json'

foo = JSON['{ "command" : {
   "param" : { "field" : "val", "otherField":"otherVal" },
   "param" : { "field" : "val", "otherField":"otherVal" },
   "param" : { "field" : "val", "otherField":"otherVal" }
    }
}']

foo # => {"command"=>{"param"=>{"field"=>"val", "otherField"=>"otherVal"}}}

所以,我们知道这是无效的。我怀疑 JSON 只是一个写得不好的例子。由于继续发送相同的"param" 是没有意义的,因此它们应该是不同的参数名称。

关于您的代码:它不是惯用的 Ruby。

Ary = Array.new Ary.push (param.new) Ary.push (param.new) Ary.push (param.new) WrappedCmd = { "命令" => Ary }

我们会这样写:

ary = []
ary << param.new
ary << param.new
ary << param.new
wrapped_cmd = { "command" => ary }

或者更简单:

ary = [
  param.new,
  param.new,
  param.new,
]
wrapped_cmd = { "command" => ary }

甚至:

wrapped_cmd = { 
  "command" => [
      param.new,
      param.new,
      param.new,
  ] 
}
  • 常量以大写字母开头,变量以小写字母开头,因此请使用ary 而不是Ary
  • 通常我们使用[] 来初始化一个空数组,而不是Array.new。这是一个可读性的东西。
  • 通常我们使用&lt;&lt; 将元素附加到数组中。同样,这是一个可读性问题。
  • 为了便于阅读,Ruby 中的变量是用snake_case 而非camelCase 编写的。它比ItIsToReadCamelCase 更容易_to_read_snake_case。

【讨论】:

  • 我认为问题的根源在于这个 API 接受的不是正确的 JSON。 “参数”是玩具问题,但它确实期望同一个字段重复 3 次。貌似有人把旧的xml格式转成json,这样的话 stuffsecond one 既正常又合理。跨度>
  • 由于我们完全不知道 OP 在说什么 API,我们完全是在黑暗中拍摄,一切都是猜测。
  • 对期望字符串的外部(非 Ruby)系统的专有调用。字符串被记录为 json 文本,看起来像原始帖子,带有一堆重复的参数并且缺少一些数组括号。作为 ruby​​ 的新手,我认为这是我以前从未遇到过的一些 json 构造。不是在黑暗中拍摄,对所提问题的限制性回答。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-05-02
  • 1970-01-01
  • 1970-01-01
  • 2010-11-27
  • 2010-09-27
  • 2011-03-14
  • 2019-01-31
相关资源
最近更新 更多