1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
//! Derive macro implementation for [`jsonapi_core`](https://docs.rs/jsonapi_core).
//!
//! This crate provides the `#[derive(JsonApi)]` procedural macro that generates
//! `ResourceObject`, `serde::Serialize`, and `serde::Deserialize` impls
//! for user-defined JSON:API resource types. It is re-exported by `jsonapi_core`
//! under the `derive` feature (on by default) and is not intended to be used
//! directly.
use TokenStream;
use ;
/// Derive macro for JSON:API resource types.
///
/// Generates implementations of `ResourceObject`, `Serialize`, and `Deserialize` that
/// produce and consume the JSON:API resource envelope format.
///
/// # Struct-Level Attributes
///
/// | Attribute | Required | Description |
/// |-----------|----------|-------------|
/// | `#[jsonapi(type = "...")]` | yes | The JSON:API type string (e.g. `"articles"`) |
/// | `#[jsonapi(case = "...")]` | no | Output case convention: `"camelCase"`, `"snake_case"`, `"kebab-case"`, `"PascalCase"`, `"none"` |
///
/// # Field-Level Attributes
///
/// | Attribute | Description |
/// |-----------|-------------|
/// | `#[jsonapi(id)]` | Marks the resource ID field. Required, exactly one per struct. Type: `String` or `Option<String>`. |
/// | `#[jsonapi(lid)]` | Marks the local identifier field (JSON:API 1.1). At most one. Type: `Option<String>`. |
/// | `#[jsonapi(relationship)]` | Field appears in `relationships`, not `attributes`. Must be `Relationship<T>` or `Vec<Relationship<T>>`. |
/// | `#[jsonapi(relationship, type = "...")]` | Relationship with explicit target type for `TypeInfo`. |
/// | `#[jsonapi(meta)]` | Maps to resource-level `meta`. At most one. Type: `Option<Meta>`. |
/// | `#[jsonapi(links)]` | Maps to resource-level `links`. At most one. Type: `Option<Links>`. |
/// | `#[jsonapi(rename = "...")]` | Override the wire name for this field. |
/// | `#[jsonapi(skip)]` | Exclude from serialization and deserialization. |
///
/// Unannotated fields are serialized as attributes.
///
/// # Fuzzy Deserialization
///
/// The generated `Deserialize` impl accepts all common case variants of each field
/// name (camelCase, snake_case, kebab-case, PascalCase). This handles servers with
/// inconsistent casing. Output casing is controlled by `#[jsonapi(case = "...")]`.
///
/// # Compile-Time Validation
///
/// The macro rejects invalid usage at compile time:
/// - Missing `#[jsonapi(id)]` field
/// - Duplicate `id`, `lid`, `meta`, or `links` annotations
/// - Invalid type string or rename value (per JSON:API member-name rules)
/// - `type = "..."` on non-relationship fields
///
/// # Example
///
/// ```ignore
/// use jsonapi_core::{JsonApi, Relationship, Meta, Links};
///
/// #[derive(Debug, Clone, PartialEq, JsonApi)]
/// #[jsonapi(type = "articles", case = "camelCase")]
/// struct Article {
/// #[jsonapi(id)]
/// id: String,
/// title: String,
/// word_count: u32,
/// #[jsonapi(relationship, type = "people")]
/// author: Relationship<Person>,
/// #[jsonapi(meta)]
/// extra: Option<Meta>,
/// #[jsonapi(links)]
/// resource_links: Option<Links>,
/// #[jsonapi(skip)]
/// cached: Option<String>,
/// }
/// ```
///
/// This generates `impl ResourceObject for Article` providing `resource_type()` → `"articles"`,
/// a `Serialize` impl producing the JSON:API envelope with camelCase member names
/// (`wordCount`), and a `Deserialize` impl accepting any common casing.