#json-xml #json #xml #serde-json #xml2json #regex #xml-to-json

quickxml_to_serde

使用 quickxml 和 serde 在 XML 和 JSON 之间进行转换

10 个版本 (5 个破坏性更新)

使用旧的 Rust 2015

0.6.0 2024年2月19日
0.5.0 2022年1月27日
0.4.3 2021年6月24日
0.4.1 2020年10月19日
0.1.0 2018年6月1日

#305 in 解析器实现

Download history 531/week @ 2024-04-20 370/week @ 2024-04-27 587/week @ 2024-05-04 684/week @ 2024-05-11 631/week @ 2024-05-18 514/week @ 2024-05-25 606/week @ 2024-06-01 533/week @ 2024-06-08 747/week @ 2024-06-15 788/week @ 2024-06-22 501/week @ 2024-06-29 352/week @ 2024-07-06 542/week @ 2024-07-13 520/week @ 2024-07-20 587/week @ 2024-07-27 590/week @ 2024-08-03

2,306 下载/月
8 个crate中使用(直接使用6个)

MIT 协议

46KB
674

quickxml_to_serde

使用 quick-xmlserde 将 XML 转换为 JSON。受 node2object 启发。

使用示例

基本

依赖

use std::fs::File;
use std::io::prelude::*;
use quickxml_to_serde::xml_string_to_json;

Rust 代码执行转换

// read an XML file into a string
let mut xml_file = File::open("test.xml")?;
let mut xml_contents = String::new();
xml_file.read_to_string(&mut xml_contents)?;

// convert the XML string into JSON with default config params
let json = xml_string_to_json(xml_contents, &Config::new_with_defaults());

println!("{}", json);

自定义配置

以下配置示例将默认行为更改为

  1. 将数字开头的数字视为字符串。例如,0001 将被转换为 "0001"
  2. 不要为从属性创建的 JSON 属性添加前缀
  3. text 作为 XML 文本节点值的 JSON 属性名称,其中文本与其他节点混合
  4. 排除输出中的空元素
let conf = Config::new_with_custom_values(true, "", "text", NullValue::Ignore);

强制执行 JSON 类型

基于绝对路径或正则表达式进行匹配

您可以覆盖 XML 中的绝对路径的类型

let config = Config::new_with_defaults()
	.add_json_type_override("/a/b", JsonArray::Always(JsonType::AlwaysString));

或者您可以根据正则表达式进行匹配!

let config = Config::new_with_defaults()
	.add_json_type_override(
		Regex::new(r"element").unwrap(),
			JsonArray::Always(JsonType::Infer)
		);

字符串

此库的默认操作是尝试推断标量数据类型,这些类型可以是 JSON 中的 intfloatboolstring。有时这并不理想,如以下示例所示。假设属性 id 总是数字,可以安全地转换为 JSON 整数。第一个两个用户的 card_number 元素看起来像数字,而第三个用户的 card_number 元素是字符串。这种 JSON 类型的不一致性使得反序列化结构变得困难,所以我们可能更愿意告诉转换器为某些 XML 节点使用特定的 JSON 数据类型。

<users>
	<user id="1">
		<name>Andrew</name>
		<card_number>000156</card_number>
	</user>
	<user id="2">
		<name>John</name>
		<card_number>100263</card_number>
	</user>
	<user id="3">
		<name>Mary</name>
		<card_number>100263a</card_number>
	</user>
</users>

在您的Cargo.toml文件中使用quickxml_to_serde = { version = "0.4", features = ["json_types"] }特性来启用对某些XML节点使用类似xPath的表示法强制JSON类型的支持。

示例XML文档

<a attr1="007"><b attr1="7">true</b></a>

配置使得属性attr1="007"始终以JSON字符串形式出现

let conf = Config::new_with_defaults().add_json_type_override("/a/@attr1", JsonArray::Infer(JsonType::AlwaysString));

配置使得<b />的属性和文本节点始终以JSON字符串形式出现

let conf = Config::new_with_defaults()
		  .add_json_type_override("/a/@attr1", JsonArray::Infer(JsonType::AlwaysString))
		  .add_json_type_override("/a/b/@attr1", JsonArray::Infer(JsonType::AlwaysString))
		  .add_json_type_override("/a/b", JsonArray::Infer(JsonType::AlwaysString));

布尔值

JSON中有效的布尔值只有两个:truefalse。另一方面,像TrueFalse10这样的值在编程语言和数据格式中很常见。使用带有“true”值列表的JsonType::Bool(...)类型将任意布尔值转换为JSON布尔值。

let conf = Config::new_with_defaults()
		.add_json_type_override("/a/b", JsonArray::Infer(JsonType::Bool(vec!["True","true","1","yes"])));

数组

具有相同名称的多个节点会自动转换为JSON数组。例如,

<a>
  <b>1</b>
  <b>2</b>
</a>

被转换为

{ "a":
  { "b": [1,2] }
}

默认情况下,单个元素如

<a>
  <b>1</b>
</a>

被转换为标量值或映射

{ "a":
  { "b": 1 }
}

您可以使用add_json_type_override()JsonArray::Always()一起使用,以创建无论元素数量如何的JSON数组,使<a><b>1</b></a>变为{ "a": { "b": [1] } }

JsonArray::Always()JsonArray::Infer()可以指定应使用的底层JSON类型,例如。

  • JsonArray::Infer(JsonType::AlwaysString) - 推断数组,将值转换为JSON字符串
  • JsonArray::Always(JsonType::Infer) - 总是包裹值在JSON数组中,推断值类型
  • JsonArray::Always(JsonType::AlwaysString) - 总是将值包装在JSON数组中并将值转换为JSON字符串
let config = Config::new_with_defaults()
		.add_json_type_override("/a/b", JsonArray::Always(JsonType::AlwaysString));

空XML节点(如 <a><b /></a>)的转换取决于 NullValue 设置。例如,

let config = Config::new_with_custom_values(false, "@", "#text", NullValue::Ignore)
		.add_json_type_override("/a/b", JsonArray::Always(JsonType::Infer));

<a><b /></a> 转换为

{"a": null}

相同的 configNullValue::Null 转换为

{"a": { "b": [null] }}

无法得到空数组,例如 {"a": { "b": [] }}


有关 Config 结构及其成员的详细信息,请参阅嵌入式文档。

转换细节

  • XML元素的顺序不保留
  • 命名空间标识符被删除。例如,<xs:a>123</xs:a> 变为 { "a":123 }
  • 整数和浮点数被转换为JSON整数和浮点数,除非在 Config 中指定了JSON类型。
  • XML属性成为与子元素同一级别的JSON属性。例如。
<Test TestId="0001">
  <Input>1</Input>
</Test>

被转换为

"Test":
  {
	"Input": 1,
	"TestId": "0001"
  }
  • XML声明被删除。例如,<?xml version="1.0"?>
  • XML命名空间定义被删除。例如,<Tests xmlns="http://www.adatum.com" /> 变为 "Tests":{}
  • 忽略处理指令、注释和DTD
  • XML中的CDATA导致JSON格式错误
  • XML属性可以通过Config::xml_attr_prefix进行前缀命名。例如,使用默认前缀@<a b="y" />转换为{ "a": {"@b":"y"} }。您可以选择不使用前缀或设置自己的值。
  • 具有文本节点的复杂XML元素将XML文本节点值放入名为Config::xml_text_node_prop_name的JSON属性中。例如,将xml_text_node_prop_name设置为text将转换
<CardNumber Month="3" Year="19">1234567</CardNumber>

{
  "CardNumber": {
		  "Month": 3,
		  "Year": 19,
		  "text": 1234567
		}
}
  • 具有相同名称的元素会被收集到数组中。例如。
<Root>
  <TaxRate>7.25</TaxRate>
  <Data>
	<Category>A</Category>
	<Quantity>3</Quantity>
	<Price>24.50</Price>
  </Data>
  <Data>
	<Category>B</Category>
	<Quantity>1</Quantity>
	<Price>89.99</Price>
  </Data>
</Root>

被转换为

{
  "Root": {
	"Data": [
	  {
		"Category": "A",
		"Price": 24.5,
		"Quantity": 3
	  },
	  {
		"Category": "B",
		"Price": 89.99,
		"Quantity": 1
	  }
	],
	"TaxRate": 7.25
  }
}
  • 如果将上述示例中的TaxRate元素插入到Data元素之间,它仍然会生成相同的JSON,其中所有Data属性被组合成一个单独的数组。

更多信息与示例

有关更多用法示例,请参阅tests.rs

边缘情况

XML和JSON不是直接兼容的,需要进行1:1转换,除非转换器有额外的提示。如果您遇到任何不正确的转换,请提交一个问题。

依赖

~4–6MB
~107K SLoC