|
| 1 | +# Codec Module Overview |
| 2 | + |
| 3 | +The `aether-datafixers-codec` module provides `DynamicOps` implementations for various data serialization formats. These implementations enable Aether Datafixers to work with JSON, YAML, TOML, and XML data. |
| 4 | + |
| 5 | +## Supported Formats |
| 6 | + |
| 7 | +| Format | Implementation | Underlying Library | Data Type | |
| 8 | +|--------|----------------|-------------------|-----------| |
| 9 | +| **JSON** | `GsonOps` | Google Gson | `JsonElement` | |
| 10 | +| **JSON** | `JacksonJsonOps` | Jackson Databind | `JsonNode` | |
| 11 | +| **YAML** | `SnakeYamlOps` | SnakeYAML | `Object` (Map/List) | |
| 12 | +| **YAML** | `JacksonYamlOps` | Jackson YAML | `JsonNode` | |
| 13 | +| **TOML** | `JacksonTomlOps` | Jackson TOML | `JsonNode` | |
| 14 | +| **XML** | `JacksonXmlOps` | Jackson XML | `JsonNode` | |
| 15 | + |
| 16 | +## Quick Start |
| 17 | + |
| 18 | +### Add Dependency |
| 19 | + |
| 20 | +```xml |
| 21 | +<dependency> |
| 22 | + <groupId>de.splatgames.aether</groupId> |
| 23 | + <artifactId>aether-datafixers-codec</artifactId> |
| 24 | + <version>${aether.version}</version> |
| 25 | +</dependency> |
| 26 | +``` |
| 27 | + |
| 28 | +All format-specific dependencies are **optional**. Add only the libraries you need: |
| 29 | + |
| 30 | +```xml |
| 31 | +<!-- For GsonOps --> |
| 32 | +<dependency> |
| 33 | + <groupId>com.google.code.gson</groupId> |
| 34 | + <artifactId>gson</artifactId> |
| 35 | + <version>2.11.0</version> |
| 36 | +</dependency> |
| 37 | + |
| 38 | +<!-- For JacksonJsonOps --> |
| 39 | +<dependency> |
| 40 | + <groupId>com.fasterxml.jackson.core</groupId> |
| 41 | + <artifactId>jackson-databind</artifactId> |
| 42 | + <version>2.18.2</version> |
| 43 | +</dependency> |
| 44 | + |
| 45 | +<!-- For SnakeYamlOps --> |
| 46 | +<dependency> |
| 47 | + <groupId>org.yaml</groupId> |
| 48 | + <artifactId>snakeyaml</artifactId> |
| 49 | + <version>2.3</version> |
| 50 | +</dependency> |
| 51 | + |
| 52 | +<!-- For JacksonYamlOps --> |
| 53 | +<dependency> |
| 54 | + <groupId>com.fasterxml.jackson.dataformat</groupId> |
| 55 | + <artifactId>jackson-dataformat-yaml</artifactId> |
| 56 | + <version>2.18.2</version> |
| 57 | +</dependency> |
| 58 | + |
| 59 | +<!-- For JacksonTomlOps --> |
| 60 | +<dependency> |
| 61 | + <groupId>com.fasterxml.jackson.dataformat</groupId> |
| 62 | + <artifactId>jackson-dataformat-toml</artifactId> |
| 63 | + <version>2.18.2</version> |
| 64 | +</dependency> |
| 65 | + |
| 66 | +<!-- For JacksonXmlOps --> |
| 67 | +<dependency> |
| 68 | + <groupId>com.fasterxml.jackson.dataformat</groupId> |
| 69 | + <artifactId>jackson-dataformat-xml</artifactId> |
| 70 | + <version>2.18.2</version> |
| 71 | +</dependency> |
| 72 | +``` |
| 73 | + |
| 74 | +### Basic Usage |
| 75 | + |
| 76 | +```java |
| 77 | +// JSON with Gson |
| 78 | +import de.splatgames.aether.datafixers.codec.json.gson.GsonOps; |
| 79 | +Dynamic<JsonElement> jsonDynamic = new Dynamic<>(GsonOps.INSTANCE, jsonElement); |
| 80 | + |
| 81 | +// YAML with SnakeYAML |
| 82 | +import de.splatgames.aether.datafixers.codec.yaml.snakeyaml.SnakeYamlOps; |
| 83 | +Dynamic<Object> yamlDynamic = new Dynamic<>(SnakeYamlOps.INSTANCE, yamlData); |
| 84 | + |
| 85 | +// TOML with Jackson |
| 86 | +import de.splatgames.aether.datafixers.codec.toml.jackson.JacksonTomlOps; |
| 87 | +Dynamic<JsonNode> tomlDynamic = new Dynamic<>(JacksonTomlOps.INSTANCE, tomlNode); |
| 88 | + |
| 89 | +// XML with Jackson |
| 90 | +import de.splatgames.aether.datafixers.codec.xml.jackson.JacksonXmlOps; |
| 91 | +Dynamic<JsonNode> xmlDynamic = new Dynamic<>(JacksonXmlOps.INSTANCE, xmlNode); |
| 92 | +``` |
| 93 | + |
| 94 | +## Package Structure |
| 95 | + |
| 96 | +``` |
| 97 | +de.splatgames.aether.datafixers.codec |
| 98 | +├── json |
| 99 | +│ ├── gson/ |
| 100 | +│ │ └── GsonOps.java |
| 101 | +│ └── jackson/ |
| 102 | +│ └── JacksonJsonOps.java |
| 103 | +├── yaml |
| 104 | +│ ├── snakeyaml/ |
| 105 | +│ │ └── SnakeYamlOps.java |
| 106 | +│ └── jackson/ |
| 107 | +│ └── JacksonYamlOps.java |
| 108 | +├── toml |
| 109 | +│ └── jackson/ |
| 110 | +│ └── JacksonTomlOps.java |
| 111 | +└── xml |
| 112 | + └── jackson/ |
| 113 | + └── JacksonXmlOps.java |
| 114 | +``` |
| 115 | + |
| 116 | +## Choosing an Implementation |
| 117 | + |
| 118 | +### JSON |
| 119 | + |
| 120 | +| Feature | GsonOps | JacksonJsonOps | |
| 121 | +|---------|---------|----------------| |
| 122 | +| Library Size | ~300 KB | ~1.7 MB | |
| 123 | +| Performance | Good | Excellent | |
| 124 | +| Streaming | No | Yes | |
| 125 | +| Custom Mappers | No | Yes | |
| 126 | +| Tree Model | `JsonElement` | `JsonNode` | |
| 127 | + |
| 128 | +**Recommendation:** Use `GsonOps` for simple use cases with minimal dependencies. Use `JacksonJsonOps` when you need maximum performance or already use Jackson. |
| 129 | + |
| 130 | +### YAML |
| 131 | + |
| 132 | +| Feature | SnakeYamlOps | JacksonYamlOps | |
| 133 | +|---------|--------------|----------------| |
| 134 | +| Library Size | ~300 KB | ~100 KB + Jackson | |
| 135 | +| Native Types | Yes (Map/List) | No (JsonNode) | |
| 136 | +| YAML Features | Full | Subset | |
| 137 | +| Anchors/Aliases | Yes | Limited | |
| 138 | +| Multi-Document | Yes | Limited | |
| 139 | + |
| 140 | +**Recommendation:** Use `SnakeYamlOps` for full YAML feature support. Use `JacksonYamlOps` when you need consistent `JsonNode` handling across formats. |
| 141 | + |
| 142 | +### TOML |
| 143 | + |
| 144 | +| Feature | JacksonTomlOps | |
| 145 | +|---------|----------------| |
| 146 | +| TOML 1.0 | Yes | |
| 147 | +| Date/Time | Via String | |
| 148 | +| Inline Tables | Yes | |
| 149 | +| Arrays of Tables | Yes | |
| 150 | + |
| 151 | +**Recommendation:** `JacksonTomlOps` is the standard choice for TOML support. |
| 152 | + |
| 153 | +### XML |
| 154 | + |
| 155 | +| Feature | JacksonXmlOps | |
| 156 | +|---------|---------------| |
| 157 | +| Attributes | Via Conventions | |
| 158 | +| Namespaces | Limited | |
| 159 | +| Mixed Content | Limited | |
| 160 | +| Tree Model | JsonNode | |
| 161 | + |
| 162 | +**Recommendation:** `JacksonXmlOps` provides basic XML support. For complex XML with namespaces, consider a dedicated XML library. |
| 163 | + |
| 164 | +## Thread Safety |
| 165 | + |
| 166 | +All singleton instances (`INSTANCE`) are thread-safe and can be shared across threads: |
| 167 | + |
| 168 | +```java |
| 169 | +// Safe to use from multiple threads |
| 170 | +GsonOps.INSTANCE |
| 171 | +JacksonJsonOps.INSTANCE |
| 172 | +SnakeYamlOps.INSTANCE |
| 173 | +JacksonYamlOps.INSTANCE |
| 174 | +JacksonTomlOps.INSTANCE |
| 175 | +JacksonXmlOps.INSTANCE |
| 176 | +``` |
| 177 | + |
| 178 | +Custom instances with custom mappers are thread-safe if the underlying mapper is thread-safe. |
| 179 | + |
| 180 | +## Format Conversion |
| 181 | + |
| 182 | +Convert data between formats using different `DynamicOps`: |
| 183 | + |
| 184 | +```java |
| 185 | +// Read YAML |
| 186 | +Yaml yaml = new Yaml(); |
| 187 | +Object yamlData = yaml.load(yamlString); |
| 188 | +Dynamic<Object> yamlDynamic = new Dynamic<>(SnakeYamlOps.INSTANCE, yamlData); |
| 189 | + |
| 190 | +// Convert to JSON |
| 191 | +Dynamic<JsonElement> jsonDynamic = yamlDynamic.convert(GsonOps.INSTANCE); |
| 192 | + |
| 193 | +// Write JSON |
| 194 | +Gson gson = new GsonBuilder().setPrettyPrinting().create(); |
| 195 | +String jsonString = gson.toJson(jsonDynamic.value()); |
| 196 | +``` |
| 197 | + |
| 198 | +See [Format Conversion](../advanced/format-conversion.md) for advanced techniques. |
| 199 | + |
| 200 | +## Migration Example |
| 201 | + |
| 202 | +Apply the same migration logic to different formats: |
| 203 | + |
| 204 | +```java |
| 205 | +public class FormatAgnosticMigrator { |
| 206 | + |
| 207 | + private final AetherDataFixer fixer; |
| 208 | + |
| 209 | + public <T> Dynamic<T> migrate(Dynamic<T> input, DataVersion from, DataVersion to) { |
| 210 | + TaggedDynamic<T> tagged = new TaggedDynamic<>(TypeReferences.CONFIG, input); |
| 211 | + TaggedDynamic<T> result = fixer.update(tagged, from, to); |
| 212 | + return result.value(); |
| 213 | + } |
| 214 | +} |
| 215 | + |
| 216 | +// Use with any format |
| 217 | +migrator.migrate(jsonDynamic, v1, v2); // JSON |
| 218 | +migrator.migrate(yamlDynamic, v1, v2); // YAML |
| 219 | +migrator.migrate(tomlDynamic, v1, v2); // TOML |
| 220 | +migrator.migrate(xmlDynamic, v1, v2); // XML |
| 221 | +``` |
| 222 | + |
| 223 | +## Related Documentation |
| 224 | + |
| 225 | +- [JSON Support](json.md) — GsonOps and JacksonJsonOps details |
| 226 | +- [YAML Support](yaml.md) — SnakeYamlOps and JacksonYamlOps details |
| 227 | +- [TOML Support](toml.md) — JacksonTomlOps details |
| 228 | +- [XML Support](xml.md) — JacksonXmlOps details |
| 229 | +- [Dynamic System](../concepts/dynamic-system.md) — Core Dynamic concepts |
| 230 | +- [Codec System](../concepts/codec-system.md) — Encoding and decoding |
| 231 | +- [Custom DynamicOps](../tutorials/custom-dynamicops.md) — Create your own implementation |
0 commit comments