如何将两个 JSON 对象与 Rust 合并?
How can I merge two JSON objects with Rust?
我有两个 JSON 文件:
JSON 1
{
"title": "This is a title",
"person" : {
"firstName" : "John",
"lastName" : "Doe"
},
"cities":[ "london", "paris" ]
}
JSON 2
{
"title": "This is another title",
"person" : {
"firstName" : "Jane"
},
"cities":[ "colombo" ]
}
我想将 #2 合并到 #1 中,其中 #2 覆盖 #1,产生以下输出:
{
"title": "This is another title",
"person" : {
"firstName" : "Jane",
"lastName" : "Doe"
},
"cities":[ "colombo" ]
}
我检查了板条箱 json-patch which does this but it does not compile against stable Rust. Is it possible to do something similar with something like serde_json 和稳定的 Rust?
这对我有用
#[macro_use]
extern crate serde_json;
use serde_json::Value;
fn merge(a: &mut Value, b: &Value) {
match (a, b) {
(&mut Value::Object(ref mut a), &Value::Object(ref b)) => {
for (k, v) in b {
merge(a.entry(k.clone()).or_insert(Value::Null), v);
}
}
(a, b) => {
*a = b.clone();
}
}
}
fn main() {
let mut a = json!({
"title": "This is a title",
"person" : {
"firstName" : "John",
"lastName" : "Doe"
},
"cities":[ "london", "paris" ]
});
let b = json!({
"title": "This is another title",
"person" : {
"firstName" : "Jane"
},
"cities":[ "colombo" ]
});
merge(&mut a, &b);
println!("{:#}", a);
}
将 Shepmaster 建议的答案放在下面
#[macro_use]
extern crate serde_json;
use serde_json::Value;
fn merge(a: &mut Value, b: Value) {
match (a, b) {
(a @ &mut Value::Object(_), Value::Object(b)) => {
let a = a.as_object_mut().unwrap();
for (k, v) in b {
merge(a.entry(k).or_insert(Value::Null), v);
}
}
(a, b) => *a = b,
}
}
fn main() {
let mut a = json!({
"title": "This is a title",
"person" : {
"firstName" : "John",
"lastName" : "Doe"
},
"cities":[ "london", "paris" ]
});
let b = json!({
"title": "This is another title",
"person" : {
"firstName" : "Jane"
},
"cities":[ "colombo" ]
});
merge(&mut a, b);
println!("{:#}", a);
}
因为您想使用 json-patch, I assume you were looking specifically for a JSON Merge Patch (RFC 7396) 实现,因为那是那个 crate 实现的。在那种情况下,合并一个对象应该取消设置那些在补丁中对应值为 null
的键,其他答案中的代码示例没有实现。
说明这一点的代码如下。我修改了补丁以删除 person.lastName
键,将其设置为 null
作为演示。与其他答案之一不同,它也不需要 unwrap()
as_object_mut()
返回的 Option
。
use serde_json::{json, Value};
fn merge(a: &mut Value, b: Value) {
if let Value::Object(a) = a {
if let Value::Object(b) = b {
for (k, v) in b {
if v.is_null() {
a.remove(&k);
}
else {
merge(a.entry(k).or_insert(Value::Null), v);
}
}
return;
}
}
*a = b;
}
fn main() {
let mut a = json!({
"title": "This is a title",
"person" : {
"firstName" : "John",
"lastName" : "Doe"
},
"cities":[ "london", "paris" ]
});
let b = json!({
"title": "This is another title",
"person" : {
"firstName" : "Jane",
"lastName": null
},
"cities":[ "colombo" ]
});
merge(&mut a, b);
println!("{:#}", a);
}
预期输出为
{
"cities": [
"colombo"
],
"person": {
"firstName": "Jane"
},
"title": "This is another title"
}
通知 person.lastName
已取消设置。
我有两个 JSON 文件:
JSON 1
{
"title": "This is a title",
"person" : {
"firstName" : "John",
"lastName" : "Doe"
},
"cities":[ "london", "paris" ]
}
JSON 2
{
"title": "This is another title",
"person" : {
"firstName" : "Jane"
},
"cities":[ "colombo" ]
}
我想将 #2 合并到 #1 中,其中 #2 覆盖 #1,产生以下输出:
{
"title": "This is another title",
"person" : {
"firstName" : "Jane",
"lastName" : "Doe"
},
"cities":[ "colombo" ]
}
我检查了板条箱 json-patch which does this but it does not compile against stable Rust. Is it possible to do something similar with something like serde_json 和稳定的 Rust?
这对我有用
#[macro_use]
extern crate serde_json;
use serde_json::Value;
fn merge(a: &mut Value, b: &Value) {
match (a, b) {
(&mut Value::Object(ref mut a), &Value::Object(ref b)) => {
for (k, v) in b {
merge(a.entry(k.clone()).or_insert(Value::Null), v);
}
}
(a, b) => {
*a = b.clone();
}
}
}
fn main() {
let mut a = json!({
"title": "This is a title",
"person" : {
"firstName" : "John",
"lastName" : "Doe"
},
"cities":[ "london", "paris" ]
});
let b = json!({
"title": "This is another title",
"person" : {
"firstName" : "Jane"
},
"cities":[ "colombo" ]
});
merge(&mut a, &b);
println!("{:#}", a);
}
将 Shepmaster 建议的答案放在下面
#[macro_use]
extern crate serde_json;
use serde_json::Value;
fn merge(a: &mut Value, b: Value) {
match (a, b) {
(a @ &mut Value::Object(_), Value::Object(b)) => {
let a = a.as_object_mut().unwrap();
for (k, v) in b {
merge(a.entry(k).or_insert(Value::Null), v);
}
}
(a, b) => *a = b,
}
}
fn main() {
let mut a = json!({
"title": "This is a title",
"person" : {
"firstName" : "John",
"lastName" : "Doe"
},
"cities":[ "london", "paris" ]
});
let b = json!({
"title": "This is another title",
"person" : {
"firstName" : "Jane"
},
"cities":[ "colombo" ]
});
merge(&mut a, b);
println!("{:#}", a);
}
因为您想使用 json-patch, I assume you were looking specifically for a JSON Merge Patch (RFC 7396) 实现,因为那是那个 crate 实现的。在那种情况下,合并一个对象应该取消设置那些在补丁中对应值为 null
的键,其他答案中的代码示例没有实现。
说明这一点的代码如下。我修改了补丁以删除 person.lastName
键,将其设置为 null
作为演示。与其他答案之一不同,它也不需要 unwrap()
as_object_mut()
返回的 Option
。
use serde_json::{json, Value};
fn merge(a: &mut Value, b: Value) {
if let Value::Object(a) = a {
if let Value::Object(b) = b {
for (k, v) in b {
if v.is_null() {
a.remove(&k);
}
else {
merge(a.entry(k).or_insert(Value::Null), v);
}
}
return;
}
}
*a = b;
}
fn main() {
let mut a = json!({
"title": "This is a title",
"person" : {
"firstName" : "John",
"lastName" : "Doe"
},
"cities":[ "london", "paris" ]
});
let b = json!({
"title": "This is another title",
"person" : {
"firstName" : "Jane",
"lastName": null
},
"cities":[ "colombo" ]
});
merge(&mut a, b);
println!("{:#}", a);
}
预期输出为
{
"cities": [
"colombo"
],
"person": {
"firstName": "Jane"
},
"title": "This is another title"
}
通知 person.lastName
已取消设置。