I was thinking about creating a HashMap<String, Span>
from your json file where the keys are every field of your json (flattened) and the values are just pointers to the substring where you can retrieve the raw value. Here some pseudo-code:
// Could be helpful to parse the value later
enum Type {
Number,
String,
EscapedString,
Object,
Array,
Bool,
Null,
}
struct Span {
start: usize, // first byte of value inside json string
end: usize, // last byte of value inside json string
typ: Type,
}
as for an interface, I was imagining something like this:
use std::collection::HashMap;
fn main() {
let json = r#"{
"foo": 1,
"bar": {
"baz": "hello"
},
"bat": [
"world"
]
}"#;
let index: HashMap<String, Span> = index_json(json).unwrap();
// index: {
// "foo": Span { start: .., end: .., type: Number },
// "bar": Span { start: .., end: .., type: Object },
// "bar.baz": Span { start: .., end: .., type: String },
// "bat": Span { start: .., end: .., type: Array },
// "bat[0]": Span {start: .., end: .., type: String },
// }
}
fn index_json(json: &str) -> Result<HashMap<String, Span>, Error> {
// ...
}
As to how I would implement it, I'm pretty sure you can do it with serde, writing your own deserializer. I personally would try an use lalrpop for that, though I'm not 100% sure how exactly to do it (I'm not sure if lalrpop lets me retrieve the start and end indices of a value).
Having said all this, I think @jonasbb's solution is far less work and quite elegant.