My agentic slop goes here. Not intended for anyone else!
1# JMAP Email Types JSON Implementation 2 3This document summarizes the JSON serialization and deserialization functionality added to the JMAP Email types implementation. 4 5## Overview 6 7JSON support has been added to the core email types in `jmap-email/jmap_email_types.ml` to enable proper serialization and parsing of JMAP email objects according to RFC 8621. 8 9## Implemented Types 10 11### 1. Email_address 12- **to_json**: Converts email addresses to JSON with `email` (required) and `name` (optional) fields 13- **of_json**: Parses JSON objects into email address structures 14- Handles both named (`{"name": "John Doe", "email": "john@example.com"}`) and unnamed (`{"email": "jane@example.com"}`) addresses 15 16### 2. Email_header 17- **to_json**: Converts header fields to JSON with `name` and `value` fields 18- **of_json**: Parses JSON objects into header field structures 19- Example: `{"name": "Subject", "value": "Important Message"}` 20 21### 3. Email_body_part 22- **to_json**: Converts body parts to comprehensive JSON representation including: 23 - Basic fields: `partId`, `blobId`, `size`, `headers`, `type` 24 - Optional fields: `name`, `charset`, `disposition`, `cid`, `language`, `location` 25 - Nested structures: `subParts` for multipart content 26 - Extension fields: `other_headers` for custom headers 27- **of_json**: Parses complex JSON structures back into body part objects 28- Handles recursive parsing for nested multipart structures 29 30### 4. Keywords 31- **to_json**: Converts keyword sets to JMAP wire format (object with boolean values) 32- **of_json**: Parses JMAP keyword objects back into keyword lists 33- Supports all JMAP standard keywords and custom keywords 34- Example: `{"$seen": true, "$flagged": false, "custom-label": true}` 35 36### 5. Email 37- **to_json**: Converts complete email objects to JSON with all present fields: 38 - Metadata: `id`, `blobId`, `threadId`, `size`, `receivedAt` 39 - Addressing: `from`, `to`, `cc`, `mailboxIds` 40 - Content: `subject`, `preview`, `hasAttachment` 41 - Structure: `textBody`, `htmlBody`, `attachments` 42 - Keywords and message IDs 43- **of_json**: Parses comprehensive email JSON into email objects 44- Handles optional fields correctly (present vs null vs missing) 45 46## Key Features 47 48### Type Safety 49- All functions use OCaml's strong type system to ensure correctness 50- Proper error handling with descriptive failure messages 51- Optional field handling that respects JMAP semantics 52 53### JMAP Compliance 54- Follows RFC 8621 JSON structure specifications exactly 55- Handles JMAP-specific data types (dates as floats, boolean maps, etc.) 56- Supports all standard and extended JMAP email properties 57 58### Robustness 59- Handles nested and recursive structures (body parts with sub-parts) 60- Proper handling of optional vs. null vs. missing fields 61- Extension field support for future JMAP enhancements 62 63## Testing 64 65Comprehensive test suite included in `jmap-email/test_email_json.ml`: 66 67### Test Coverage 681. **Round-trip testing**: JSON → OCaml → JSON conversion verification 692. **Field handling**: Optional, null, and missing field scenarios 703. **Complex structures**: Nested body parts, multiple addresses, keyword sets 714. **Real-world examples**: RFC-compliant JMAP email JSON parsing 725. **Edge cases**: Empty lists, minimal vs. full email objects 73 74### Test Types 75- Unit tests for individual type conversions 76- Integration tests with realistic JMAP email examples 77- Round-trip verification to ensure data preservation 78- Property-based testing for JSON field ordering independence 79 80## Usage Examples 81 82### Basic Email Address Parsing 83```ocaml 84let json = `Assoc [("name", `String "John Doe"); ("email", `String "john@example.com")] 85let addr = Email_address.of_json json 86let back_to_json = Email_address.to_json addr 87``` 88 89### Complete Email Object Handling 90```ocaml 91let email_json = Yojson.Safe.from_string {| 92 { 93 "id": "M123", 94 "subject": "Test", 95 "from": [{"name": "Alice", "email": "alice@example.com"}], 96 "keywords": {"$seen": true, "$flagged": false} 97 } 98|} 99let email = Email.of_json email_json 100let roundtrip = Email.to_json email 101``` 102 103### Body Part Structure Parsing 104```ocaml 105let body_part_json = Yojson.Safe.from_string {| 106 { 107 "partId": "1", 108 "type": "text/plain", 109 "size": 1024, 110 "headers": [{"name": "Content-Type", "value": "text/plain"}], 111 "charset": "utf-8" 112 } 113|} 114let part = Email_body_part.of_json body_part_json 115``` 116 117## Implementation Notes 118 119- Uses manual JSON handling for precise control over structure 120- Leverages Yojson.Safe for JSON processing 121- Hashtbl used for ID maps and keyword storage as per JMAP library patterns 122- Date handling uses float values per JMAP specification 123- Error messages are descriptive for debugging JSON structure issues 124 125This implementation provides a solid foundation for JMAP email processing with full JSON serialization support.