# jcard
[](https://github.com/ticpu/jcard/actions/workflows/ci.yml)
[](https://crates.io/crates/jcard)
[](https://docs.rs/jcard)
[](https://crates.io/crates/jcard)
[](https://github.com/ticpu/jcard#license)
[RFC 7095](https://www.rfc-editor.org/rfc/rfc7095) jCard (JSON representation
of vCard) types with serde support.
All value types from RFC 7095 §3.5 are supported: text, uri, date, time,
date-time, date-and-or-time, timestamp, boolean, integer, float,
utc-offset, language-tag, and unknown. Structured property values with
nested arrays (§3.3.1.3) are handled. Type identifiers are stored
separately for round-trip fidelity, including extension types.
## Usage
```toml
[dependencies]
jcard = "0.3"
```
### Builder
```rust
use jcard::JCard;
let jcard = JCard::builder()
.fn_("Jane Doe")
.n("Doe", "Jane", "", "", "")
.email("jane.doe@example.com")
.build();
let json = serde_json::to_string_pretty(&jcard).unwrap();
let parsed: JCard = serde_json::from_str(&json).unwrap();
assert_eq!(jcard, parsed);
```
### Lenient parsing with warnings
```rust
use jcard::JCard;
let parsed = JCard::from_json(r#"["vcard",[
["version",{},"text","4.0"],
["fn",{},"text","Jane Doe"],
["email","bad-params","text","jane@example.com"]
]]"#).unwrap();
// Best-effort result is always available
assert_eq!(parsed.value.properties().len(), 3);
// Warnings report what went wrong
for w in &parsed.warnings {
eprintln!("{w}");
}
```
## Deserialization behavior
The serde `Deserialize` impl returns `Err` on structurally invalid jCard
input (wrong tag, not an array, etc.) by default. This is the expected
behavior for standalone use — the caller sees the error and decides what
to do.
When jCard is embedded as a field in a parent struct (e.g., EIDO's
`agencyJcard: Option<JCard>`), a deserialization error on the jCard
poisons the entire parent. Enable the `lenient-deserialize` feature to
return an empty `JCard` (with only the mandatory `version` property)
instead of `Err`:
```toml
[dependencies]
jcard = { version = "0.3", features = ["lenient-deserialize"] }
```
Both paths discard warnings. Use `from_json()` or `from_value()` when
you need structured warning collection alongside the best-effort result.
### From an existing serde_json::Value
```rust
use jcard::JCard;
let value: serde_json::Value = serde_json::from_str(
r#"["vcard",[["version",{},"text","4.0"],["fn",{},"text","Test"]]]"#
).unwrap();
let parsed = JCard::from_value(&value).unwrap();
assert!(!parsed.has_warnings());
```
## License
Licensed under either of
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE))
- MIT License ([LICENSE-MIT](LICENSE-MIT))
at your option.