不使用 stdlib 将 Ruby 哈希数组转换为 JSON(漂亮)?
Convert array of Ruby hashes to JSON (pretty) not using stdlib?
根据问题,只是想知道如何在不使用 Ruby stdlib 'JSON' 模块(以及 JSON.pretty_generate 方法)的情况下执行此操作。
所以我有一个哈希数组,如下所示:
[{"h1"=>"a", "h2"=>"b", "h3"=>"c"}, {"h1"=>"d", "h2"=>"e", "h3"=>"f"}]
我想将其转换为如下所示:
[
{
"h1": "a",
"h2": "b",
"h3": "c",
},
{
"h1": "d",
"h2": "e",
"h3": "f",
}
]
我可以使用简单的 gsub (array_of_hashes.to_s.gsub!(/=>/, ": ")) 将哈希火箭替换为冒号空格,但不确定如何生成它以便它看起来像上面的例子。我最初想过使用 here-doc 方法来执行此操作,但不确定这是最好的方法,而且我还没有设法让它工作。我是 Ruby 的新手,如果这很明显,我深表歉意! :-)
def to_json_pretty
json_pretty = <<-EOM
[
{
"#{array_of_hashes.each { |hash| puts hash } }"
},
]
EOM
json_pretty
end
如果您输入的格式与您提供的格式完全一致,而不是嵌套,那么这应该能正常工作:
a = [{"h1"=>"a", "h2"=>"b", "h3"=>"c"}, {"h1"=>"d", "h2"=>"e", "h3"=>"f"}]
hstart = 0
astart = 0
a.each do |b|
puts "[" if astart == 0
astart+=1
b.each do |key, value|
puts " {" if hstart == 0
hstart += 1
puts " " + key.to_s + ' : ' + value
if hstart % 2 == 0
if hstart == a.collect(&:size).reduce(:+)
puts " }"
else
puts " },\n {"
end
end
end
puts "]" if astart == a.size
end
输出:
[
{
h1 : a
h2 : b
},
{
h3 : c
h1 : d
},
{
h2 : e
h3 : f
}
]
一般来说,要在不使用库的情况下很好地使用 JSON 需要的不仅仅是几行代码。话虽如此,JSON 化事物的最佳方式通常是递归地进行,例如:
def pretty_json(obj)
case obj
when Array
contents = obj.map {|x| pretty_json(x).gsub(/^/, " ") }.join(",\n")
"[\n#{contents}\n]"
when Hash
contents = obj.map {|k, v| "#{pretty_json(k.to_s)}: #{pretty_json(v)}".gsub(/^/, " ") }.join(",\n")
"{\n#{contents}\n}"
else
obj.inspect
end
end
你可以看看我的NeatJSON gem for how I did it. Specifically, look at neatjson.rb
,它使用递归解决方案(通过过程)。
根据您提供的格式化选项,我的代码有很多变化,因此它显然不必如此复杂。但一般模式是测试提供给 method/proc 的对象类型,如果它很简单则将其序列化,或者(如果它是数组或散列)为其中的每个值重新调用 method/proc。
这是一个大大简化的版本(没有缩进、没有换行、硬编码间距):
def simple_json(object)
js = ->(o) do
case o
when String then o.inspect
when Symbol then o.to_s.inspect
when Numeric then o.to_s
when TrueClass,FalseClass then o.to_s
when NilClass then "null"
when Array then "[ #{o.map{ |v| js[v] }.join ', '} ]"
when Hash then "{ #{o.map{ |k,v| [js[k],js[v]].join ":"}.join ', '} }"
else
raise "I don't know how to deal with #{o.inspect}"
end
end
js[object]
end
puts simple_json({a:1,b:[2,3,4],c:3})
#=> { "a":1, "b":[ 2, 3, 4 ], "c":3 }
根据问题,只是想知道如何在不使用 Ruby stdlib 'JSON' 模块(以及 JSON.pretty_generate 方法)的情况下执行此操作。
所以我有一个哈希数组,如下所示:
[{"h1"=>"a", "h2"=>"b", "h3"=>"c"}, {"h1"=>"d", "h2"=>"e", "h3"=>"f"}]
我想将其转换为如下所示:
[
{
"h1": "a",
"h2": "b",
"h3": "c",
},
{
"h1": "d",
"h2": "e",
"h3": "f",
}
]
我可以使用简单的 gsub (array_of_hashes.to_s.gsub!(/=>/, ": ")) 将哈希火箭替换为冒号空格,但不确定如何生成它以便它看起来像上面的例子。我最初想过使用 here-doc 方法来执行此操作,但不确定这是最好的方法,而且我还没有设法让它工作。我是 Ruby 的新手,如果这很明显,我深表歉意! :-)
def to_json_pretty
json_pretty = <<-EOM
[
{
"#{array_of_hashes.each { |hash| puts hash } }"
},
]
EOM
json_pretty
end
如果您输入的格式与您提供的格式完全一致,而不是嵌套,那么这应该能正常工作:
a = [{"h1"=>"a", "h2"=>"b", "h3"=>"c"}, {"h1"=>"d", "h2"=>"e", "h3"=>"f"}]
hstart = 0
astart = 0
a.each do |b|
puts "[" if astart == 0
astart+=1
b.each do |key, value|
puts " {" if hstart == 0
hstart += 1
puts " " + key.to_s + ' : ' + value
if hstart % 2 == 0
if hstart == a.collect(&:size).reduce(:+)
puts " }"
else
puts " },\n {"
end
end
end
puts "]" if astart == a.size
end
输出:
[
{
h1 : a
h2 : b
},
{
h3 : c
h1 : d
},
{
h2 : e
h3 : f
}
]
一般来说,要在不使用库的情况下很好地使用 JSON 需要的不仅仅是几行代码。话虽如此,JSON 化事物的最佳方式通常是递归地进行,例如:
def pretty_json(obj)
case obj
when Array
contents = obj.map {|x| pretty_json(x).gsub(/^/, " ") }.join(",\n")
"[\n#{contents}\n]"
when Hash
contents = obj.map {|k, v| "#{pretty_json(k.to_s)}: #{pretty_json(v)}".gsub(/^/, " ") }.join(",\n")
"{\n#{contents}\n}"
else
obj.inspect
end
end
你可以看看我的NeatJSON gem for how I did it. Specifically, look at neatjson.rb
,它使用递归解决方案(通过过程)。
根据您提供的格式化选项,我的代码有很多变化,因此它显然不必如此复杂。但一般模式是测试提供给 method/proc 的对象类型,如果它很简单则将其序列化,或者(如果它是数组或散列)为其中的每个值重新调用 method/proc。
这是一个大大简化的版本(没有缩进、没有换行、硬编码间距):
def simple_json(object)
js = ->(o) do
case o
when String then o.inspect
when Symbol then o.to_s.inspect
when Numeric then o.to_s
when TrueClass,FalseClass then o.to_s
when NilClass then "null"
when Array then "[ #{o.map{ |v| js[v] }.join ', '} ]"
when Hash then "{ #{o.map{ |k,v| [js[k],js[v]].join ":"}.join ', '} }"
else
raise "I don't know how to deal with #{o.inspect}"
end
end
js[object]
end
puts simple_json({a:1,b:[2,3,4],c:3})
#=> { "a":1, "b":[ 2, 3, 4 ], "c":3 }