CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-hjson--hjson

Hjson (Human JSON) configuration file format library for Java providing parsing and generation capabilities with human-friendly features.

Pending
Overview
Eval results
Files

configuration.mddocs/

Configuration and Options

Configure parsing behavior and output formatting with HjsonOptions and Domain Specific Format providers for specialized value handling and custom parsing rules.

Capabilities

HjsonOptions Configuration

Configure parsing and formatting behavior for Hjson operations.

/**
 * Configuration options for Hjson parsing and formatting
 */
class HjsonOptions {
    /**
     * Creates default Hjson options with standard settings
     */
    HjsonOptions();
    
    /**
     * Gets the array of Domain Specific Format providers
     * @return array of DSF providers, or null if none are configured
     */
    IHjsonDsfProvider[] getDsfProviders();
    
    /**
     * Sets the Domain Specific Format providers for specialized value parsing and formatting
     * @param providers array of DSF providers to use, or null to disable DSF processing
     */
    void setDsfProviders(IHjsonDsfProvider[] providers);
    
    /**
     * Gets whether legacy root parsing is enabled (objects without braces)
     * @return true if legacy root parsing is enabled
     */
    boolean getParseLegacyRoot();
    
    /**
     * Sets whether to parse legacy root format (object members without surrounding braces)
     * @param value true to enable legacy root parsing
     */
    void setParseLegacyRoot(boolean value);
    
    /**
     * Gets whether root braces are emitted in output (deprecated, always returns true)
     * @return always true
     * @deprecated Root braces are always emitted in current versions
     */
    @Deprecated
    boolean getEmitRootBraces();
    
    /**
     * Sets whether to emit root braces in output (deprecated, no-op)
     * @param value ignored, root braces are always emitted
     * @deprecated Root braces are always emitted in current versions
     */
    @Deprecated
    void setEmitRootBraces(boolean value);
}

Usage Examples:

import org.hjson.HjsonOptions;
import org.hjson.JsonValue;
import org.hjson.HjsonDsf;

// Create options with default settings
HjsonOptions options = new HjsonOptions();

// Configure DSF providers for specialized parsing
options.setDsfProviders(new IHjsonDsfProvider[] {
    HjsonDsf.math(),
    HjsonDsf.hex(true)
});

// Enable legacy root parsing (objects without braces)
options.setParseLegacyRoot(true);

// Use options for parsing
JsonValue result = JsonValue.readHjson("""
    // This is valid with legacy root parsing
    name: My Application
    version: "1.0.0"
    maxValue: +Inf
    hexColor: 0xFF0000
    """, options);

// Use options for formatting
String formatted = result.toString(options);
System.out.println(formatted);

Domain Specific Format Providers

Extend parsing and formatting capabilities with specialized value handlers.

/**
 * Interface for implementing Domain Specific Format providers
 * DSF providers handle specialized value parsing and formatting
 */
interface IHjsonDsfProvider {
    /**
     * Gets the name of this DSF provider
     * @return the provider name
     */
    String getName();
    
    /**
     * Gets a description of what this DSF provider handles
     * @return the provider description
     */
    String getDescription();
    
    /**
     * Attempts to parse the given text as a specialized value
     * @param text the text to parse
     * @return JsonValue representing the parsed value, or null if not handled by this provider
     */
    JsonValue parse(String text);
    
    /**
     * Attempts to convert the given JsonValue back to specialized string format
     * @param value the JsonValue to convert
     * @return string representation, or null if not handled by this provider
     */
    String stringify(JsonValue value);
}

Built-in DSF Providers

Standard Domain Specific Format providers for common specialized values.

/**
 * Utility class providing standard DSF providers
 */
class HjsonDsf {
    /**
     * Returns a math DSF provider that handles mathematical constants and special values
     * Supports: +Inf, -Inf, Inf, +NaN, NaN, -NaN, -0
     * @return math DSF provider
     */
    static IHjsonDsfProvider math();
    
    /**
     * Returns a hex DSF provider that handles hexadecimal number notation
     * Parses: 0x prefixed hexadecimal numbers (e.g., 0xFF, 0x123ABC)
     * @param stringify whether to format numbers back to hex notation during output
     * @return hex DSF provider
     */
    static IHjsonDsfProvider hex(boolean stringify);
}

Usage Examples:

import org.hjson.HjsonDsf;
import org.hjson.JsonValue;
import org.hjson.HjsonOptions;
import org.hjson.IHjsonDsfProvider;

// Math DSF provider usage
IHjsonDsfProvider mathProvider = HjsonDsf.math();
System.out.println("Math provider: " + mathProvider.getName());
System.out.println("Description: " + mathProvider.getDescription());

// Parse mathematical constants
HjsonOptions mathOptions = new HjsonOptions();
mathOptions.setDsfProviders(new IHjsonDsfProvider[] { mathProvider });

JsonValue infinityValue = JsonValue.readHjson("{ max: +Inf, min: -Inf, invalid: NaN }", mathOptions);
System.out.println("Parsed infinity: " + infinityValue.asObject().get("max").asDouble()); // Infinity

// Hex DSF provider usage
IHjsonDsfProvider hexProvider = HjsonDsf.hex(true); // Enable hex output
HjsonOptions hexOptions = new HjsonOptions();
hexOptions.setDsfProviders(new IHjsonDsfProvider[] { hexProvider });

JsonValue hexValue = JsonValue.readHjson("{ color: 0xFF0000, mask: 0x00FF00 }", hexOptions);
System.out.println("Red color: " + hexValue.asObject().get("color").asInt()); // 16711680

// Combined DSF providers
HjsonOptions combinedOptions = new HjsonOptions();
combinedOptions.setDsfProviders(new IHjsonDsfProvider[] {
    HjsonDsf.math(),
    HjsonDsf.hex(true)
});

JsonValue combined = JsonValue.readHjson("""
    {
        maxValue: +Inf
        hexColor: 0xFF0000
        invalidResult: NaN
        bitmask: 0xFFFF
    }
    """, combinedOptions);

String output = combined.toString(combinedOptions);
System.out.println("Combined output:");
System.out.println(output);

Legacy Root Parsing

Support for parsing Hjson objects without surrounding braces (legacy format).

/**
 * Legacy root parsing allows parsing of object members without surrounding braces
 * Useful for configuration files that omit the root object braces
 */
boolean getParseLegacyRoot();
void setParseLegacyRoot(boolean value);

Usage Examples:

import org.hjson.HjsonOptions;
import org.hjson.JsonValue;
import org.hjson.JsonObject;

// Enable legacy root parsing
HjsonOptions legacyOptions = new HjsonOptions();
legacyOptions.setParseLegacyRoot(true);

// Parse configuration without root braces
String legacyConfig = """
    // Application configuration
    appName: My Application
    version: "1.0.0"
    port: 8080
    debug: true
    
    // Database settings
    dbHost: localhost
    dbPort: 5432
    dbName: myapp_db
    """;

JsonValue config = JsonValue.readHjson(legacyConfig, legacyOptions);
JsonObject configObj = config.asObject();

String appName = configObj.getString("appName", "");
int port = configObj.getInt("port", 3000);
boolean debug = configObj.getBoolean("debug", false);

System.out.println("App: " + appName + ", Port: " + port + ", Debug: " + debug);

// Standard parsing (requires braces)
HjsonOptions standardOptions = new HjsonOptions();
standardOptions.setParseLegacyRoot(false); // Default behavior

try {
    JsonValue standard = JsonValue.readHjson(legacyConfig, standardOptions);
    // This will throw ParseException because root braces are missing
} catch (ParseException e) {
    System.err.println("Standard parsing failed: " + e.getMessage());
}

// Same content with braces works with standard parsing
String bracedConfig = "{ " + legacyConfig + " }";
JsonValue braced = JsonValue.readHjson(bracedConfig, standardOptions);

Custom DSF Provider Implementation

Creating Custom DSF Providers

import org.hjson.IHjsonDsfProvider;
import org.hjson.JsonValue;
import java.util.regex.Pattern;
import java.util.regex.Matcher;

/**
 * Example DSF provider for ISO date strings
 */
public class DateDsfProvider implements IHjsonDsfProvider {
    private static final Pattern ISO_DATE_PATTERN = 
        Pattern.compile("^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{3})?Z?$");
    
    @Override
    public String getName() {
        return "date";
    }
    
    @Override
    public String getDescription() {
        return "Handles ISO 8601 date strings";
    }
    
    @Override
    public JsonValue parse(String text) {
        if (text != null && ISO_DATE_PATTERN.matcher(text).matches()) {
            // Store as string but mark as date for special handling
            return JsonValue.valueOf(text);
        }
        return null; // Not handled by this provider
    }
    
    @Override  
    public String stringify(JsonValue value) {
        if (value.isString()) {
            String str = value.asString();
            if (ISO_DATE_PATTERN.matcher(str).matches()) {
                return str; // Return without quotes in Hjson
            }
        }
        return null; // Not handled by this provider
    }
}

// Usage
HjsonOptions dateOptions = new HjsonOptions();
dateOptions.setDsfProviders(new IHjsonDsfProvider[] {
    new DateDsfProvider(),
    HjsonDsf.math()
});

JsonValue dateData = JsonValue.readHjson("""
    {
        created: 2023-12-01T10:30:00Z
        updated: 2023-12-01T15:45:30.123Z
        expires: +Inf  // Math DSF still works
    }
    """, dateOptions);

URL DSF Provider Example

/**  
 * DSF provider for URL validation and handling
 */
public class UrlDsfProvider implements IHjsonDsfProvider {
    private static final Pattern URL_PATTERN = 
        Pattern.compile("^https?://[\\w\\-]+(\\.[\\w\\-]+)*([\\w\\-\\.,@?^=%&:/~\\+#]*[\\w\\-\\@?^=%&/~\\+#])?$");
    
    @Override
    public String getName() {
        return "url";
    }
    
    @Override
    public String getDescription() {
        return "Handles HTTP and HTTPS URLs";
    }
    
    @Override
    public JsonValue parse(String text) {
        if (text != null && URL_PATTERN.matcher(text).matches()) {
            return JsonValue.valueOf(text);
        }
        return null;
    }
    
    @Override
    public String stringify(JsonValue value) {
        if (value.isString()) {
            String str = value.asString();
            if (URL_PATTERN.matcher(str).matches()) {
                return str; // Output without quotes
            }
        }
        return null;
    }
}

// Usage with multiple custom providers
HjsonOptions customOptions = new HjsonOptions();
customOptions.setDsfProviders(new IHjsonDsfProvider[] {
    new DateDsfProvider(),
    new UrlDsfProvider(),
    HjsonDsf.hex(false)
});

JsonValue webConfig = JsonValue.readHjson("""
    {
        apiEndpoint: https://api.example.com/v1
        webhookUrl: https://webhook.example.com/notify
        created: 2023-12-01T10:30:00Z
        maxRetries: 0xFF  // Hex number
    }
    """, customOptions);

Configuration Patterns

Environment-Specific Configuration

import org.hjson.HjsonOptions;
import org.hjson.JsonValue;
import org.hjson.JsonObject;

public class ConfigurationManager {
    private final HjsonOptions productionOptions;
    private final HjsonOptions developmentOptions;
    
    public ConfigurationManager() {
        // Production: strict parsing, minimal DSF
        productionOptions = new HjsonOptions();
        productionOptions.setParseLegacyRoot(false);
        productionOptions.setDsfProviders(new IHjsonDsfProvider[] {
            HjsonDsf.math() // Only math constants
        });
        
        // Development: lenient parsing, full DSF support
        developmentOptions = new HjsonOptions();
        developmentOptions.setParseLegacyRoot(true);
        developmentOptions.setDsfProviders(new IHjsonDsfProvider[] {
            HjsonDsf.math(),
            HjsonDsf.hex(true),
            new DateDsfProvider(),
            new UrlDsfProvider()
        });
    }
    
    public JsonObject loadConfig(String configText, boolean isProduction) {
        HjsonOptions options = isProduction ? productionOptions : developmentOptions;
        return JsonValue.readHjson(configText, options).asObject();
    }
}

DSF Provider Chaining

public class ChainedDsfProvider implements IHjsonDsfProvider {
    private final List<IHjsonDsfProvider> providers;
    
    public ChainedDsfProvider(IHjsonDsfProvider... providers) {
        this.providers = Arrays.asList(providers);
    }
    
    @Override
    public String getName() {
        return "chained";
    }
    
    @Override
    public String getDescription() {
        return "Chains multiple DSF providers";
    }
    
    @Override
    public JsonValue parse(String text) {
        for (IHjsonDsfProvider provider : providers) {
            JsonValue result = provider.parse(text);
            if (result != null) {
                return result;
            }
        }
        return null;
    }
    
    @Override
    public String stringify(JsonValue value) {
        for (IHjsonDsfProvider provider : providers) {
            String result = provider.stringify(value);
            if (result != null) {
                return result;
            }
        }
        return null;
    }
}

// Usage
HjsonOptions chainedOptions = new HjsonOptions();
chainedOptions.setDsfProviders(new IHjsonDsfProvider[] {
    new ChainedDsfProvider(
        new DateDsfProvider(),
        new UrlDsfProvider(),
        HjsonDsf.math(),
        HjsonDsf.hex(true)
    )
});

Performance and Best Practices

DSF Provider Performance

// Efficient DSF provider implementation
public class OptimizedDsfProvider implements IHjsonDsfProvider {
    // Pre-compile patterns for better performance
    private static final Pattern PATTERN = Pattern.compile("...");
    
    // Cache compiled patterns and frequently used values
    private final Map<String, JsonValue> parseCache = new ConcurrentHashMap<>();
    
    @Override
    public JsonValue parse(String text) {
        if (text == null || text.isEmpty()) {
            return null; // Quick exit for empty strings
        }
        
        // Check cache first
        JsonValue cached = parseCache.get(text);
        if (cached != null) {
            return cached;
        }
        
        // Perform parsing and cache result
        if (PATTERN.matcher(text).matches()) {
            JsonValue result = JsonValue.valueOf(text);
            parseCache.put(text, result);
            return result;
        }
        
        return null;
    }
}

Configuration Best Practices

  1. Provider Order: Place more specific providers before general ones
  2. Caching: Cache HjsonOptions instances for repeated use
  3. Error Handling: DSF providers should never throw exceptions
  4. Performance: Keep DSF provider logic simple and fast
  5. Validation: Validate DSF provider inputs thoroughly
  6. Documentation: Clearly document custom DSF provider behavior
// Good configuration management
public class ConfigManager {
    private static final HjsonOptions DEFAULT_OPTIONS = createDefaultOptions();
    
    private static HjsonOptions createDefaultOptions() {
        HjsonOptions options = new HjsonOptions();
        options.setDsfProviders(new IHjsonDsfProvider[] {
            HjsonDsf.math(),
            HjsonDsf.hex(true)
        });
        return options;
    }
    
    public static JsonValue parseConfig(String text) {
        return JsonValue.readHjson(text, DEFAULT_OPTIONS);
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-org-hjson--hjson

docs

configuration.md

index.md

json-arrays.md

json-objects.md

parsing.md

serialization.md

types-exceptions.md

tile.json