mirror of
https://github.com/Brandon-Rozek/website.git
synced 2024-10-30 01:12:07 -04:00
104 lines
3.2 KiB
Markdown
104 lines
3.2 KiB
Markdown
|
---
|
||
|
title: "Modifying JSON in Rust"
|
||
|
date: 2024-08-03T07:59:15-07:00
|
||
|
draft: false
|
||
|
tags: []
|
||
|
math: false
|
||
|
medium_enabled: false
|
||
|
---
|
||
|
|
||
|
For my new role, I've been learning Rust. I don't know why I didn't learn it earlier, I enjoy it so much that I decided to power my [toots](/toots) page with it.
|
||
|
|
||
|
When I query my toots, I receive a JSON response like the following:
|
||
|
|
||
|
```json
|
||
|
[{"id": "112581869512127927", ..., "content": "...",}, ...]
|
||
|
```
|
||
|
|
||
|
Some parts of the JSON response changes quite frequently. Since I [archive](https://brandonrozek.com/blog/archiving-toots/) the changes, I want to strip out the highly dynamic information before saving it off to a file.
|
||
|
|
||
|
```rust
|
||
|
let mut json_response: serde_json::Value = serde_json::from_str("...")
|
||
|
.expect("JSON parse error");
|
||
|
```
|
||
|
|
||
|
In order to modify this variable, we need to have some knowledge of it's structure. I'll show in this post how to modify our JSON data given whether we're working with a JSON array or a JSON object.
|
||
|
|
||
|
## `serde_json::Value::Array`
|
||
|
|
||
|
Our example JSON starts off as an array, so let's extract that out:
|
||
|
|
||
|
```rust
|
||
|
let json_array = json_response
|
||
|
.as_array_mut()
|
||
|
.expect("Expected JSON Array");
|
||
|
```
|
||
|
|
||
|
The `as_array_mut` says to interpret the `json_response` variable as an array. The `mut` component is important for us to be able to edit the data in place without making copies.
|
||
|
|
||
|
The `as_array_mut` method returns an option type. Calling `.expect(...)` on it will cause the program to crash if it isn't indeed an array. We can alternatively perform some error handling:
|
||
|
|
||
|
```rust
|
||
|
if let Some(json_array) = json_response.as_array_mut() {
|
||
|
// Do something with json_array
|
||
|
} else {
|
||
|
// Error handling here
|
||
|
}
|
||
|
```
|
||
|
|
||
|
Though I'll assume that you're following best practices and not discuss more about error handling in this post.
|
||
|
|
||
|
Our variable `json_array` has type `&mut Vec<serde_json::Value>`which means we can do things like add another element to said array.
|
||
|
|
||
|
```rust
|
||
|
let new_element = serde_json::Value::from(1);
|
||
|
json_array.push(new_element);
|
||
|
```
|
||
|
|
||
|
We can also remove the last element of the array if it exists
|
||
|
|
||
|
```rust
|
||
|
json_array.pop()
|
||
|
```
|
||
|
|
||
|
## `serde_json::Value::Object`
|
||
|
|
||
|
Within the array, we have a list of objects. Let us grab the first element as an example:
|
||
|
|
||
|
```rust
|
||
|
let first_item = json_array.get_mut(0).unwrap();
|
||
|
```
|
||
|
|
||
|
In order to be able to modify the data, we use the `get_mut` method. This, like before, returns an option if it doesn't exist. We can call `unwrap` on it to get access to the data or panic if the element doesn't exist.
|
||
|
|
||
|
The variable `first_item` has type `serde_json::Value`. To interpret this as an object, we need to call `as_object_mut`.
|
||
|
|
||
|
```rust
|
||
|
let first_item_obj = first_item.as_object_mut().unwrap();
|
||
|
```
|
||
|
|
||
|
Now our variable `first_item_obj` has type `&mut Map<String, serde_json::Value>`.
|
||
|
|
||
|
We can remove any fields that we don't think is important
|
||
|
|
||
|
```rust
|
||
|
first_item_obj.remove("bot");
|
||
|
```
|
||
|
|
||
|
Add any fields we want
|
||
|
|
||
|
```rust
|
||
|
let new_key = "PoweredBy".to_string();
|
||
|
let new_value = serde_json::Value::from("Rust");
|
||
|
toot.insert(new_key, new_value);
|
||
|
```
|
||
|
|
||
|
Renaming a field is the combination of the last two:
|
||
|
|
||
|
```rust
|
||
|
let toot_date = toot.remove("created_at")
|
||
|
.expect("Missing created_at");
|
||
|
toot.insert("date".to_string(), toot_date);
|
||
|
```
|
||
|
|