https://github.com/bluk/json-feed-model
A Rust implementation of JSON Feed model types using Serde JSON.
https://github.com/bluk/json-feed-model
feed feeds json-feed jsonfeed rust serde serde-json syndication
Last synced: 6 months ago
JSON representation
A Rust implementation of JSON Feed model types using Serde JSON.
- Host: GitHub
- URL: https://github.com/bluk/json-feed-model
- Owner: bluk
- License: apache-2.0
- Created: 2020-10-08T19:03:20.000Z (about 5 years ago)
- Default Branch: trunk
- Last Pushed: 2025-03-17T02:55:51.000Z (7 months ago)
- Last Synced: 2025-03-17T03:03:25.278Z (7 months ago)
- Topics: feed, feeds, json-feed, jsonfeed, rust, serde, serde-json, syndication
- Language: Rust
- Homepage: https://docs.rs/json-feed-model/
- Size: 51.8 KB
- Stars: 0
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE-APACHE
Awesome Lists containing this project
README
# JSON Feed Model
[JSON Feed][jsonfeed] Model provides types which can be used to manipulate JSON
Feed data.The crate is basically a [newtype][newtype] wrapper around [Serde
JSON][serde_json]'s `Map` type and provides methods to JSON Feed properties.For example, a library user can have a slice of bytes and create a `Feed` by
calling `from_slice`. If the slice of bytes is a JSON object, then a `Feed`
instance is returned. The only guarantee which `Feed` and other model types make
is that the JSON data is a JSON object.The library user can call `is_valid(Version::Version1_1)` on the `Feed` instance
to determine if the JSON object is a valid Version 1.1 JSON Feed.## Documentation
* [Latest API Docs][api_docs]
## Installation
By default, features which depend on the Rust `std` library are included.
```toml
[dependencies]
json-feed-model = "0.2.0"
```### Alloc Only
If the host environment has an allocator but does not have access to the Rust `std` library:
```toml
[dependencies]
json-feed-model = { version = "0.2.0", default-features = false, features = ["alloc"]}
```# Accessor Methods
If the library user wants to read or write data, then methods like `title()`,
`set_title(...)`, and `remove_title()` exist on `Feed`.For "getter" methods, the return type is a `Result, ...>`. The
"getter" may fail due to expecting the wrong JSON type. For instance, if a field
is expected to be a JSON string but the value is a JSON number, then an
`Error::UnexpectedType` will be returned. The field value may or may not be
present so the `Option` type is used to indicate if a value exists.For "setter" and "remove" methods, any existing value in the JSON object is
returned.# Owned, Borrowed, and Borrowed Mutable Types
There are 3 variants of every model type, the "owned" data type (e.g. `Feed`),
the borrowed data type (e.g. `FeedRef`), and the borrowed mutable data type
(e.g. `FeedMut`). In most cases, the "owned" data type will be the primary kind
explicitly used. The borrowed and borrowed mutable variants may be returned from
"getter" methods for performance reasons.A few standard traits are implemented like `From>` and
`Serialize` as well as a few helper methods like `as_map()` and `as_map_mut()`
for the model types.## Examples
The following example shows how to read properties.
```rust
use json_feed_model::{Feed, ItemRef, Version};let json = serde_json::json!({
"version": "https://jsonfeed.org/version/1.1",
"title": "Lorem ipsum dolor sit amet.",
"home_page_url": "https://example.org/",
"feed_url": "https://example.org/feed.json",
"items": [
{
"id": "cd7f0673-8e81-4e13-b273-4bd1b83967d0",
"content_text": "Aenean tristique dictum mauris, et.",
"url": "https://example.org/aenean-tristique"
},
{
"id": "2bcb497d-c40b-4493-b5ae-bc63c74b48fa",
"content_html": "Vestibulum non magna vitae tortor.",
"url": "https://example.org/vestibulum-non"
}
]
});let feed = json_feed_model::from_value(json)?;
assert!(feed.is_valid(&Version::Version1_1));
assert_eq!(feed.version()?, Some(json_feed_model::VERSION_1_1));
assert_eq!(feed.title()?, Some("Lorem ipsum dolor sit amet."));
assert_eq!(feed.home_page_url()?, Some("https://example.org/"));
assert_eq!(feed.feed_url()?, Some("https://example.org/feed.json"));let items: Option> = feed.items()?;
assert!(items.is_some());
let items: Vec = items.unwrap();
assert_eq!(items.len(), 2);assert_eq!(items[0].id()?, Some("cd7f0673-8e81-4e13-b273-4bd1b83967d0"));
assert_eq!(
items[0].content_text()?,
Some("Aenean tristique dictum mauris, et.")
);
assert_eq!(
items[0].url()?,
Some("https://example.org/aenean-tristique")
);assert_eq!(items[1].id()?, Some("2bcb497d-c40b-4493-b5ae-bc63c74b48fa"));
assert_eq!(
items[1].content_html()?,
Some("Vestibulum non magna vitae tortor.")
);
assert_eq!(items[1].url()?, Some("https://example.org/vestibulum-non"));
# Ok::<(), json_feed_model::Error>(())
```### Custom Extension
The following example uses a custom trait to write and then read a custom extension.
It also shows a simple way to use `serde_json` to write the JSON Feed. See
`serde_json` for other serialization methods.```rust
use json_feed_model::{Feed, Item, Version};
use serde_json::Value;trait ExampleExtension {
fn example(&self) -> Result, json_feed_model::Error>;fn set_example(&mut self, value: T) -> Option
where
T: ToString;
}impl ExampleExtension for Feed {
fn example(&self) -> Result, json_feed_model::Error> {
self.as_map().get("_example").map_or_else(
|| Ok(None),
|value| match value {
Value::String(s) => Ok(Some(s.as_str())),
_ => Err(json_feed_model::Error::UnexpectedType),
},
)
}fn set_example(&mut self, value: T) -> Option
where
T: ToString,
{
self.as_map_mut()
.insert(String::from("_example"), Value::String(value.to_string()))
}
}let mut feed = Feed::new();
feed.set_version(Version::Version1_1);
feed.set_title("Lorem ipsum dolor sit amet.");feed.set_example("123456");
let mut item = Item::new();
item.set_id("2bcb497d-c40b-4493-b5ae-bc63c74b48fa");
item.set_content_text("Vestibulum non magna vitae tortor.");
item.set_url("https://example.org/vestibulum-non");feed.set_items(vec![item]);
assert!(feed.is_valid(&Version::Version1_1));
let expected_json = serde_json::json!({
"version": "https://jsonfeed.org/version/1.1",
"title": "Lorem ipsum dolor sit amet.",
"_example": "123456",
"items": [
{
"id": "2bcb497d-c40b-4493-b5ae-bc63c74b48fa",
"content_text": "Vestibulum non magna vitae tortor.",
"url": "https://example.org/vestibulum-non",
}
]
});
assert_eq!(feed, json_feed_model::from_value(expected_json)?);assert_eq!(feed.example()?, Some("123456"));
let output = serde_json::to_string(&feed);
assert!(output.is_ok());
# Ok::<(), json_feed_model::Error>(())
```## License
Licensed under either of [Apache License, Version 2.0][license_apache] or [MIT
License][license_mit] at your option.### Contributions
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.[license_apache]: LICENSE-APACHE
[license_mit]: LICENSE-MIT
[jsonfeed]: https://jsonfeed.org/
[newtype]: https://doc.rust-lang.org/rust-by-example/generics/new_types.html
[serde_json]: https://github.com/serde-rs/json
[api_docs]: https://docs.rs/json-feed-model/