Как перебирать объекты JSON в иерархии?
Я хочу напечатать name
каждого контакта в объекте глубоко в иерархии. Контактный объект может не иметь одинаковое количество полей каждый раз, чтобы создать подходящую структуру. Как мне этого добиться?
extern crate serde_json;
use serde_json::{Error, Value};
use std::collections::HashMap;
fn untyped_example() -> Result<(), Error> {
// Some JSON input data as a &str. Maybe this comes from the user.
let data = r#"{
"name":"John Doe",
"age":43,
"phones":[
"+44 1234567",
"+44 2345678"
],
"contact":{
"name":"Stefan",
"age":23,
"optionalfield":"dummy field",
"phones":[
"12123",
"345346"
],
"contact":{
"name":"James",
"age":34,
"phones":[
"23425",
"98734"
]
}
}
}"#;
let mut d: HashMap<String, Value> = serde_json::from_str(&data)?;
for (str, val) in d {
println!("{}", str);
if str == "contact" {
d = serde_json::from_value(val)?;
}
}
Ok(())
}
fn main() {
untyped_example().unwrap();
}
Я очень новичок в Rust и в основном из JavaScript.
2 ответа
Прочитав перечисление serde_json::value::Value, я нашел то, что вы искали:
extern crate serde_json;
use serde_json::{Value};
fn main() {
let data = r#"{
"name":"John Doe",
"age":43,
"phones":[
"+44 1234567",
"+44 2345678"
],
"contact":{
"name":"Stefan",
"age":23,
"optionalfield":"dummy field",
"phones":[
"12123",
"345346"
],
"contact":{
"name":"James",
"age":34,
"phones":[
"23425",
"98734"
]
}
}
}"#;
let data: Value = serde_json::from_str(data).unwrap();
read_value(&data, "name");
}
fn read_value(value: &Value, search_word: &str) {
for val in value.as_object().unwrap(){
let (key, v) = val;
if key == "name" {
println!("> name: {}",v);
}
if v.is_object() { // if it is an object, check recursively
read_value(&v, search_word);
}
}
}
Это можно было бы сделать нерекурсивным способом, но это была более простая форма, которую я мог придумать. Кроме того, я думаю, что рекурсивная реализация выглядит намного элегантнее и короче для такого рода задач.
может не иметь одинаковое количество полей каждый раз, чтобы создать подходящую структуру
Непонятно, почему вы так думаете:
extern crate serde_json; // 1.0.24
#[macro_use]
extern crate serde_derive; // 1.0.70;
use serde_json::Error;
#[derive(Debug, Deserialize)]
struct Contact {
name: String,
contact: Option<Box<Contact>>,
}
impl Contact {
fn print_names(&self) {
println!("{}", self.name);
let mut current = self;
while let Some(ref c) = current.contact {
println!("{}", c.name);
current = &c;
}
}
}
fn main() -> Result<(), Error> {
let data = r#"{
"name":"John Doe",
"contact":{
"name":"Stefan",
"contact":{
"name":"James"
}
}
}"#;
let person: Contact = serde_json::from_str(data)?;
person.print_names();
Ok(())
}
Я удалил дополнительные поля из JSON, чтобы иметь меньший пример, но ничего не меняется, если они присутствуют.
Смотрите также: