An open API service indexing awesome lists of open source software.

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.

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/