Rails如何将含嵌套数组的Hash转XML且去除数组外层包裹标签
解决Ruby Hash转XML时数组标签重复嵌套的问题
问题背景
你有这样一个带嵌套数组的Hash:
hash = { Sender_Name: "Bob", Consignement: { Load_Type: "FCL", JobContainer: [ {c_number: "123"}, {c_number: 456} ] } }
使用to_xml转换后,JobContainer数组被多套了一层同名外层标签,不符合预期格式。
解决方案
要去掉这层多余的外层标签,我们可以修改ActiveSupport::XmlMini的默认处理逻辑,让数组直接生成同级的子标签,而不是被包裹。
具体做法是重写to_tag方法,调整数组的处理逻辑:
module ActiveSupport module XmlMini module_function def to_tag(name, value, options = {}) if value.is_a?(Array) # 遍历数组,为每个元素生成对应名称的标签,跳过外层包裹 value.map { |v| to_tag(name, v, options) }.join else attributes = options[:attributes] || {} if value.respond_to?(:to_xml) value.to_xml(options.merge(root: name)) else content = encode_value(value, options) "<#{name}#{attributes.map { |k, v| " #{k}=\"#{v}\"" }.join}>#{content}</#{name}>" end end end end end
之后再执行你的to_xml调用:
hash.to_xml(skip_instruct: true, skip_types: true, root: "Consolidation2")
就能得到你想要的XML结果:
<Consolidation2> <Sender-Name>Bob</Sender-Name> <Consignement> <Load-Type>FCL</Load-Type> <JobContainer> <c-number>123</c-number> </JobContainer> <JobContainer> <c-number>456</c-number> </JobContainer> </Consignement> </Consolidation2>
这个修改的核心是:当处理数组类型的值时,不再生成一个和数组键名相同的外层标签,而是直接为数组中的每个元素生成对应键名的标签,完美解决了嵌套冗余的问题。
内容的提问来源于stack exchange,提问作者mahi-man
相关产品推荐
相关产品推荐

