hkelley44
hkelley44

Reputation: 1

Reading in just the first item from a JSON file into a Rust variable

I have a json file in the following format:

[
  {
    "end_date": "2024-02-20 16:31:12",
    "instrument": "BTC-1MAR24-36000-C",
    "start_date": "2024-02-12 00:00:02"
  },
  {
    "end_date": "2024-02-20 16:31:12",
    "instrument": "BTC-1MAR24-36000-P",
    "start_date": "2024-02-12 00:00:04"
  }
]

In my Rust program I want to process just the first object in this array. I am having trouble with the serde_json::Deserializer module. Whenever I try to process just the first item I end up reading in the entire array of items. The assumption here is that the file migh be incredibly large so i do not want to read in the entire contents of the file, only the first item.

The following is one of the variations I have tried. Any thoughts? Thanks!

fn main() {
    let file = File::open("contract_start_end.json").expect("Failed to open file");
    let reader = BufReader::new(file);
    let mut deserializer = Deserializer::from_reader(reader).into_iter::<Value>();

    if let Some(first_object) = deserializer.next() {
        match first_object {
            Ok(json) => println!("{:?}", json),
            Err(e) => println!("Error parsing JSON: {}", e),
        }
    }
}

Upvotes: 0

Views: 201

Answers (1)

Chayim Friedman
Chayim Friedman

Reputation: 71535

This is a hack, but you can skip the first [ then serde_json will read the first object and stop:

let file = File::open("contract_start_end.json").expect("Failed to open file");
let mut reader = BufReader::new(file);
// skip_until() is a better fit here, but it's unstable.
reader
    .read_until(b'[', &mut Vec::new())
    .expect("error reading file");
let mut deserializer = Deserializer::from_reader(reader).into_iter::<Value>();

if let Some(first_object) = deserializer.next() {
    match first_object {
        Ok(json) => println!("{:#?}", json),
        Err(e) => println!("Error parsing JSON: {}", e),
    }
}

If you need multiple objects, you can skip the commas too:

let file = File::open("contract_start_end.json").expect("Failed to open file");
let mut reader = BufReader::new(file);
// skip_until() is a better fit here, but it's unstable.
reader
    .read_until(b'[', &mut Vec::new())
    .expect("error reading file");
for i in 0..2 {
    let mut deserializer = Deserializer::from_reader(&mut reader).into_iter::<Value>();
    
    if let Some(object) = deserializer.next() {
        match object {
            Ok(json) => println!("{:#?}", json),
            Err(e) => println!("Error parsing JSON: {}", e),
        }
    }
    
    reader
        .read_until(b',', &mut Vec::new())
        .expect("error reading file");
}

Upvotes: 0

Related Questions