0
# Configuration and Options
1
2
Configure parsing behavior and output formatting with HjsonOptions and Domain Specific Format providers for specialized value handling and custom parsing rules.
3
4
## Capabilities
5
6
### HjsonOptions Configuration
7
8
Configure parsing and formatting behavior for Hjson operations.
9
10
```java { .api }
11
/**
12
* Configuration options for Hjson parsing and formatting
13
*/
14
class HjsonOptions {
15
/**
16
* Creates default Hjson options with standard settings
17
*/
18
HjsonOptions();
19
20
/**
21
* Gets the array of Domain Specific Format providers
22
* @return array of DSF providers, or null if none are configured
23
*/
24
IHjsonDsfProvider[] getDsfProviders();
25
26
/**
27
* Sets the Domain Specific Format providers for specialized value parsing and formatting
28
* @param providers array of DSF providers to use, or null to disable DSF processing
29
*/
30
void setDsfProviders(IHjsonDsfProvider[] providers);
31
32
/**
33
* Gets whether legacy root parsing is enabled (objects without braces)
34
* @return true if legacy root parsing is enabled
35
*/
36
boolean getParseLegacyRoot();
37
38
/**
39
* Sets whether to parse legacy root format (object members without surrounding braces)
40
* @param value true to enable legacy root parsing
41
*/
42
void setParseLegacyRoot(boolean value);
43
44
/**
45
* Gets whether root braces are emitted in output (deprecated, always returns true)
46
* @return always true
47
* @deprecated Root braces are always emitted in current versions
48
*/
49
@Deprecated
50
boolean getEmitRootBraces();
51
52
/**
53
* Sets whether to emit root braces in output (deprecated, no-op)
54
* @param value ignored, root braces are always emitted
55
* @deprecated Root braces are always emitted in current versions
56
*/
57
@Deprecated
58
void setEmitRootBraces(boolean value);
59
}
60
```
61
62
**Usage Examples:**
63
64
```java
65
import org.hjson.HjsonOptions;
66
import org.hjson.JsonValue;
67
import org.hjson.HjsonDsf;
68
69
// Create options with default settings
70
HjsonOptions options = new HjsonOptions();
71
72
// Configure DSF providers for specialized parsing
73
options.setDsfProviders(new IHjsonDsfProvider[] {
74
HjsonDsf.math(),
75
HjsonDsf.hex(true)
76
});
77
78
// Enable legacy root parsing (objects without braces)
79
options.setParseLegacyRoot(true);
80
81
// Use options for parsing
82
JsonValue result = JsonValue.readHjson("""
83
// This is valid with legacy root parsing
84
name: My Application
85
version: "1.0.0"
86
maxValue: +Inf
87
hexColor: 0xFF0000
88
""", options);
89
90
// Use options for formatting
91
String formatted = result.toString(options);
92
System.out.println(formatted);
93
```
94
95
### Domain Specific Format Providers
96
97
Extend parsing and formatting capabilities with specialized value handlers.
98
99
```java { .api }
100
/**
101
* Interface for implementing Domain Specific Format providers
102
* DSF providers handle specialized value parsing and formatting
103
*/
104
interface IHjsonDsfProvider {
105
/**
106
* Gets the name of this DSF provider
107
* @return the provider name
108
*/
109
String getName();
110
111
/**
112
* Gets a description of what this DSF provider handles
113
* @return the provider description
114
*/
115
String getDescription();
116
117
/**
118
* Attempts to parse the given text as a specialized value
119
* @param text the text to parse
120
* @return JsonValue representing the parsed value, or null if not handled by this provider
121
*/
122
JsonValue parse(String text);
123
124
/**
125
* Attempts to convert the given JsonValue back to specialized string format
126
* @param value the JsonValue to convert
127
* @return string representation, or null if not handled by this provider
128
*/
129
String stringify(JsonValue value);
130
}
131
```
132
133
### Built-in DSF Providers
134
135
Standard Domain Specific Format providers for common specialized values.
136
137
```java { .api }
138
/**
139
* Utility class providing standard DSF providers
140
*/
141
class HjsonDsf {
142
/**
143
* Returns a math DSF provider that handles mathematical constants and special values
144
* Supports: +Inf, -Inf, Inf, +NaN, NaN, -NaN, -0
145
* @return math DSF provider
146
*/
147
static IHjsonDsfProvider math();
148
149
/**
150
* Returns a hex DSF provider that handles hexadecimal number notation
151
* Parses: 0x prefixed hexadecimal numbers (e.g., 0xFF, 0x123ABC)
152
* @param stringify whether to format numbers back to hex notation during output
153
* @return hex DSF provider
154
*/
155
static IHjsonDsfProvider hex(boolean stringify);
156
}
157
```
158
159
**Usage Examples:**
160
161
```java
162
import org.hjson.HjsonDsf;
163
import org.hjson.JsonValue;
164
import org.hjson.HjsonOptions;
165
import org.hjson.IHjsonDsfProvider;
166
167
// Math DSF provider usage
168
IHjsonDsfProvider mathProvider = HjsonDsf.math();
169
System.out.println("Math provider: " + mathProvider.getName());
170
System.out.println("Description: " + mathProvider.getDescription());
171
172
// Parse mathematical constants
173
HjsonOptions mathOptions = new HjsonOptions();
174
mathOptions.setDsfProviders(new IHjsonDsfProvider[] { mathProvider });
175
176
JsonValue infinityValue = JsonValue.readHjson("{ max: +Inf, min: -Inf, invalid: NaN }", mathOptions);
177
System.out.println("Parsed infinity: " + infinityValue.asObject().get("max").asDouble()); // Infinity
178
179
// Hex DSF provider usage
180
IHjsonDsfProvider hexProvider = HjsonDsf.hex(true); // Enable hex output
181
HjsonOptions hexOptions = new HjsonOptions();
182
hexOptions.setDsfProviders(new IHjsonDsfProvider[] { hexProvider });
183
184
JsonValue hexValue = JsonValue.readHjson("{ color: 0xFF0000, mask: 0x00FF00 }", hexOptions);
185
System.out.println("Red color: " + hexValue.asObject().get("color").asInt()); // 16711680
186
187
// Combined DSF providers
188
HjsonOptions combinedOptions = new HjsonOptions();
189
combinedOptions.setDsfProviders(new IHjsonDsfProvider[] {
190
HjsonDsf.math(),
191
HjsonDsf.hex(true)
192
});
193
194
JsonValue combined = JsonValue.readHjson("""
195
{
196
maxValue: +Inf
197
hexColor: 0xFF0000
198
invalidResult: NaN
199
bitmask: 0xFFFF
200
}
201
""", combinedOptions);
202
203
String output = combined.toString(combinedOptions);
204
System.out.println("Combined output:");
205
System.out.println(output);
206
```
207
208
### Legacy Root Parsing
209
210
Support for parsing Hjson objects without surrounding braces (legacy format).
211
212
```java { .api }
213
/**
214
* Legacy root parsing allows parsing of object members without surrounding braces
215
* Useful for configuration files that omit the root object braces
216
*/
217
boolean getParseLegacyRoot();
218
void setParseLegacyRoot(boolean value);
219
```
220
221
**Usage Examples:**
222
223
```java
224
import org.hjson.HjsonOptions;
225
import org.hjson.JsonValue;
226
import org.hjson.JsonObject;
227
228
// Enable legacy root parsing
229
HjsonOptions legacyOptions = new HjsonOptions();
230
legacyOptions.setParseLegacyRoot(true);
231
232
// Parse configuration without root braces
233
String legacyConfig = """
234
// Application configuration
235
appName: My Application
236
version: "1.0.0"
237
port: 8080
238
debug: true
239
240
// Database settings
241
dbHost: localhost
242
dbPort: 5432
243
dbName: myapp_db
244
""";
245
246
JsonValue config = JsonValue.readHjson(legacyConfig, legacyOptions);
247
JsonObject configObj = config.asObject();
248
249
String appName = configObj.getString("appName", "");
250
int port = configObj.getInt("port", 3000);
251
boolean debug = configObj.getBoolean("debug", false);
252
253
System.out.println("App: " + appName + ", Port: " + port + ", Debug: " + debug);
254
255
// Standard parsing (requires braces)
256
HjsonOptions standardOptions = new HjsonOptions();
257
standardOptions.setParseLegacyRoot(false); // Default behavior
258
259
try {
260
JsonValue standard = JsonValue.readHjson(legacyConfig, standardOptions);
261
// This will throw ParseException because root braces are missing
262
} catch (ParseException e) {
263
System.err.println("Standard parsing failed: " + e.getMessage());
264
}
265
266
// Same content with braces works with standard parsing
267
String bracedConfig = "{ " + legacyConfig + " }";
268
JsonValue braced = JsonValue.readHjson(bracedConfig, standardOptions);
269
```
270
271
## Custom DSF Provider Implementation
272
273
### Creating Custom DSF Providers
274
275
```java
276
import org.hjson.IHjsonDsfProvider;
277
import org.hjson.JsonValue;
278
import java.util.regex.Pattern;
279
import java.util.regex.Matcher;
280
281
/**
282
* Example DSF provider for ISO date strings
283
*/
284
public class DateDsfProvider implements IHjsonDsfProvider {
285
private static final Pattern ISO_DATE_PATTERN =
286
Pattern.compile("^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{3})?Z?$");
287
288
@Override
289
public String getName() {
290
return "date";
291
}
292
293
@Override
294
public String getDescription() {
295
return "Handles ISO 8601 date strings";
296
}
297
298
@Override
299
public JsonValue parse(String text) {
300
if (text != null && ISO_DATE_PATTERN.matcher(text).matches()) {
301
// Store as string but mark as date for special handling
302
return JsonValue.valueOf(text);
303
}
304
return null; // Not handled by this provider
305
}
306
307
@Override
308
public String stringify(JsonValue value) {
309
if (value.isString()) {
310
String str = value.asString();
311
if (ISO_DATE_PATTERN.matcher(str).matches()) {
312
return str; // Return without quotes in Hjson
313
}
314
}
315
return null; // Not handled by this provider
316
}
317
}
318
319
// Usage
320
HjsonOptions dateOptions = new HjsonOptions();
321
dateOptions.setDsfProviders(new IHjsonDsfProvider[] {
322
new DateDsfProvider(),
323
HjsonDsf.math()
324
});
325
326
JsonValue dateData = JsonValue.readHjson("""
327
{
328
created: 2023-12-01T10:30:00Z
329
updated: 2023-12-01T15:45:30.123Z
330
expires: +Inf // Math DSF still works
331
}
332
""", dateOptions);
333
```
334
335
### URL DSF Provider Example
336
337
```java
338
/**
339
* DSF provider for URL validation and handling
340
*/
341
public class UrlDsfProvider implements IHjsonDsfProvider {
342
private static final Pattern URL_PATTERN =
343
Pattern.compile("^https?://[\\w\\-]+(\\.[\\w\\-]+)*([\\w\\-\\.,@?^=%&:/~\\+#]*[\\w\\-\\@?^=%&/~\\+#])?$");
344
345
@Override
346
public String getName() {
347
return "url";
348
}
349
350
@Override
351
public String getDescription() {
352
return "Handles HTTP and HTTPS URLs";
353
}
354
355
@Override
356
public JsonValue parse(String text) {
357
if (text != null && URL_PATTERN.matcher(text).matches()) {
358
return JsonValue.valueOf(text);
359
}
360
return null;
361
}
362
363
@Override
364
public String stringify(JsonValue value) {
365
if (value.isString()) {
366
String str = value.asString();
367
if (URL_PATTERN.matcher(str).matches()) {
368
return str; // Output without quotes
369
}
370
}
371
return null;
372
}
373
}
374
375
// Usage with multiple custom providers
376
HjsonOptions customOptions = new HjsonOptions();
377
customOptions.setDsfProviders(new IHjsonDsfProvider[] {
378
new DateDsfProvider(),
379
new UrlDsfProvider(),
380
HjsonDsf.hex(false)
381
});
382
383
JsonValue webConfig = JsonValue.readHjson("""
384
{
385
apiEndpoint: https://api.example.com/v1
386
webhookUrl: https://webhook.example.com/notify
387
created: 2023-12-01T10:30:00Z
388
maxRetries: 0xFF // Hex number
389
}
390
""", customOptions);
391
```
392
393
## Configuration Patterns
394
395
### Environment-Specific Configuration
396
397
```java
398
import org.hjson.HjsonOptions;
399
import org.hjson.JsonValue;
400
import org.hjson.JsonObject;
401
402
public class ConfigurationManager {
403
private final HjsonOptions productionOptions;
404
private final HjsonOptions developmentOptions;
405
406
public ConfigurationManager() {
407
// Production: strict parsing, minimal DSF
408
productionOptions = new HjsonOptions();
409
productionOptions.setParseLegacyRoot(false);
410
productionOptions.setDsfProviders(new IHjsonDsfProvider[] {
411
HjsonDsf.math() // Only math constants
412
});
413
414
// Development: lenient parsing, full DSF support
415
developmentOptions = new HjsonOptions();
416
developmentOptions.setParseLegacyRoot(true);
417
developmentOptions.setDsfProviders(new IHjsonDsfProvider[] {
418
HjsonDsf.math(),
419
HjsonDsf.hex(true),
420
new DateDsfProvider(),
421
new UrlDsfProvider()
422
});
423
}
424
425
public JsonObject loadConfig(String configText, boolean isProduction) {
426
HjsonOptions options = isProduction ? productionOptions : developmentOptions;
427
return JsonValue.readHjson(configText, options).asObject();
428
}
429
}
430
```
431
432
### DSF Provider Chaining
433
434
```java
435
public class ChainedDsfProvider implements IHjsonDsfProvider {
436
private final List<IHjsonDsfProvider> providers;
437
438
public ChainedDsfProvider(IHjsonDsfProvider... providers) {
439
this.providers = Arrays.asList(providers);
440
}
441
442
@Override
443
public String getName() {
444
return "chained";
445
}
446
447
@Override
448
public String getDescription() {
449
return "Chains multiple DSF providers";
450
}
451
452
@Override
453
public JsonValue parse(String text) {
454
for (IHjsonDsfProvider provider : providers) {
455
JsonValue result = provider.parse(text);
456
if (result != null) {
457
return result;
458
}
459
}
460
return null;
461
}
462
463
@Override
464
public String stringify(JsonValue value) {
465
for (IHjsonDsfProvider provider : providers) {
466
String result = provider.stringify(value);
467
if (result != null) {
468
return result;
469
}
470
}
471
return null;
472
}
473
}
474
475
// Usage
476
HjsonOptions chainedOptions = new HjsonOptions();
477
chainedOptions.setDsfProviders(new IHjsonDsfProvider[] {
478
new ChainedDsfProvider(
479
new DateDsfProvider(),
480
new UrlDsfProvider(),
481
HjsonDsf.math(),
482
HjsonDsf.hex(true)
483
)
484
});
485
```
486
487
## Performance and Best Practices
488
489
### DSF Provider Performance
490
491
```java
492
// Efficient DSF provider implementation
493
public class OptimizedDsfProvider implements IHjsonDsfProvider {
494
// Pre-compile patterns for better performance
495
private static final Pattern PATTERN = Pattern.compile("...");
496
497
// Cache compiled patterns and frequently used values
498
private final Map<String, JsonValue> parseCache = new ConcurrentHashMap<>();
499
500
@Override
501
public JsonValue parse(String text) {
502
if (text == null || text.isEmpty()) {
503
return null; // Quick exit for empty strings
504
}
505
506
// Check cache first
507
JsonValue cached = parseCache.get(text);
508
if (cached != null) {
509
return cached;
510
}
511
512
// Perform parsing and cache result
513
if (PATTERN.matcher(text).matches()) {
514
JsonValue result = JsonValue.valueOf(text);
515
parseCache.put(text, result);
516
return result;
517
}
518
519
return null;
520
}
521
}
522
```
523
524
### Configuration Best Practices
525
526
1. **Provider Order**: Place more specific providers before general ones
527
2. **Caching**: Cache HjsonOptions instances for repeated use
528
3. **Error Handling**: DSF providers should never throw exceptions
529
4. **Performance**: Keep DSF provider logic simple and fast
530
5. **Validation**: Validate DSF provider inputs thoroughly
531
6. **Documentation**: Clearly document custom DSF provider behavior
532
533
```java
534
// Good configuration management
535
public class ConfigManager {
536
private static final HjsonOptions DEFAULT_OPTIONS = createDefaultOptions();
537
538
private static HjsonOptions createDefaultOptions() {
539
HjsonOptions options = new HjsonOptions();
540
options.setDsfProviders(new IHjsonDsfProvider[] {
541
HjsonDsf.math(),
542
HjsonDsf.hex(true)
543
});
544
return options;
545
}
546
547
public static JsonValue parseConfig(String text) {
548
return JsonValue.readHjson(text, DEFAULT_OPTIONS);
549
}
550
}
551
```