Skip to content

jaschenk/dataforge-library

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

DataForge

A pure Java 25 library for processing XML and JSON with YAML-driven dynamic validation.

Zero external dependencies. Hand-written parsers. Modern Java features.


Features

  • Unified Data Model — Parse XML or JSON into a single tree structure (DataNode)
  • Hand-Written Parsers — Custom recursive descent parsers for XML, JSON, and YAML (no external libraries)
  • Get/Set by Tag Name — Retrieve or update values anywhere in the tree by tag name
  • Dot-Notation Path Access — Navigate nested structures with person.address.city syntax
  • Deep Search — Find all nodes matching a tag name or predicate across the entire tree
  • Tree Manipulation — Add, remove, clone nodes programmatically
  • Format Conversion — Convert XML to JSON and vice versa
  • YAML-Driven Validation — Define validation rules in YAML, apply them dynamically
  • Java 25 Features — Records, sealed interfaces, pattern matching, switch expressions, text blocks, SequencedCollections

Quick Start

import io.dataforge.DataForge;

// Parse XML (auto-detected)
var doc = DataForge.parse("<user><name>Alice</name><age>30</age></user>");

// Get value by tag name (deep search)
String name = doc.getValueByTag("name").orElse("unknown");

// Set value by tag name
doc.setValueByTag("age", "31");

// Get value by dot-notation path
String city = doc.getValueByPath("address.city").orElse("?");

// Convert to JSON
String json = doc.toJson();

// Validate with YAML rules
String yaml = """
    rules:
      name:
        required: true
        type: string
        minLength: 1
      age:
        type: integer
        min: 0
        max: 150
    """;
var result = doc.validate(yaml);
if (!result.isValid()) {
    System.out.println(result.report());
}

API Reference

Parsing

// Auto-detect format from content
DataForge.parse(String content)

// Explicit format
DataForge.parse(String content, DataFormat.XML)
DataForge.parse(String content, DataFormat.JSON)

// From file (format detected by extension)
DataForge.parseFile("data.xml")
DataForge.parseFile("data.json")

// Create empty document
DataForge.create("rootElementName")

Get Values

// By tag name (deep search — finds anywhere in tree)
doc.getValueByTag("tagName")              // Optional<String> — first match
doc.getAllValuesByTag("tagName")           // List<String> — all matches

// By dot-notation path
doc.getValueByPath("person.address.city") // Optional<String>
doc.getNodeByPath("person.address")       // Optional<DataNode>

// Search
doc.findFirst("tagName")                  // Optional<DataNode>
doc.findAll("tagName")                    // List<DataNode>

Set Values

// By tag name
doc.setValueByTag("tag", "newValue")      // int — updates ALL matches, returns count
doc.setFirstValueByTag("tag", "newValue") // boolean — updates first match only

// By path (creates intermediate nodes if needed)
doc.setValueByPath("a.b.c", "value")

Tree Manipulation

// Add children
doc.addChild("parentTag", "childName", "childValue")
doc.addChild("parentTag", dataNode)
doc.addToRoot("name", "value")
doc.addToRoot(dataNode)

// Remove
doc.removeByTag("tagName")               // int — returns count removed

// Clone
DataNode clone = doc.root().deepClone()

// Node info
node.path()                               // "root.person.address.city"
node.depth()                              // int
node.isLeaf()                             // boolean

Serialization & Conversion

// Serialize
doc.toXml()                               // Pretty-printed with declaration
doc.toJson()                              // Pretty-printed
doc.serialize()                           // Back to original format

// Custom writers
doc.toXml(XmlWriter.compact())
doc.toJson(JsonWriter.compact())
doc.toXml(XmlWriter.builder().declaration(false).indent("    ").build())

// Format conversion
doc.convert()                             // XML->JSON or JSON->XML
doc.convertTo(DataFormat.JSON)

// Write to file
doc.writeTo("output.xml")
doc.writeTo("output.json")

Validation

Define rules in YAML:

rules:
  username:
    required: true
    type: string
    minLength: 3
    maxLength: 20
    pattern: ^[a-zA-Z0-9_]+$
    message: "Username must be 3-20 alphanumeric characters"

  age:
    required: true
    type: integer
    min: 18
    max: 120

  email:
    required: true
    notEmpty: true

  status:
    type: string
    enum:
      - active
      - inactive
      - pending

  address:
    required: true
    type: object
    children:
      city:
        required: true
        type: string
      zip:
        required: true
        pattern: ^[0-9]{5}$

Supported validation rules:

Rule Description Example
required Field must exist true
type Type check: string, integer, number, boolean, object, array integer
min Minimum numeric value 0
max Maximum numeric value 150
minLength Minimum string length 3
maxLength Maximum string length 100
pattern Regex pattern ^[A-Z]+$
enum Allowed values list [a, b, c]
notEmpty Value must not be blank true
message Custom error message "Invalid!"
children Nested validation rules for child nodes (nested mapping)

Apply validation:

// From YAML string
ValidationResult result = doc.validate(yamlString);

// From YAML file
ValidationResult result = doc.validateWithFile("rules.yaml");

// Pre-built engine (reusable)
ValidationEngine engine = ValidationEngine.fromYaml(yamlString);
ValidationResult result = doc.validate(engine);

// Inspect results
result.isValid()                 // boolean
result.errorCount()              // int
result.getErrors()               // List<ValidationError>
result.errorsForPath("username") // errors at specific path
result.report()                  // human-readable report

Project Structure

dataforge/
  src/io/dataforge/
    DataForge.java              # Main facade API
    core/
      DataNode.java             # Unified tree data model
      DataFormat.java           # XML/JSON enum with detection
      DataForgeException.java   # Base exception
      NodeType.java             # Node type enum
    parser/
      XmlParser.java            # Hand-written XML parser
      JsonParser.java           # Hand-written JSON parser
      YamlParser.java           # Hand-written YAML parser
    writer/
      XmlWriter.java            # XML serializer with builder
      JsonWriter.java           # JSON serializer with builder
    validation/
      ValidationEngine.java     # YAML-driven validation engine
      ValidationRule.java       # Rule model
      ValidationResult.java     # Result aggregator
      ValidationError.java      # Error record
  test/io/dataforge/
    DataForgeTest.java          # 117 comprehensive tests
  demo/
    DataForgeDemo.java          # Full feature demo

Building & Running

# Requires Java 25+
export JAVA_HOME=/path/to/jdk-25
export PATH=$JAVA_HOME/bin:$PATH

# Compile library
mkdir -p build
javac -d build src/io/dataforge/core/*.java \
               src/io/dataforge/parser/*.java \
               src/io/dataforge/writer/*.java \
               src/io/dataforge/validation/*.java \
               src/io/dataforge/DataForge.java

# Run tests (117 tests)
javac -cp build -d build test/io/dataforge/DataForgeTest.java
java -cp build io.dataforge.DataForgeTest

# Run demo
javac -cp build -d build demo/DataForgeDemo.java
java -cp build io.dataforge.demo.DataForgeDemo

# Package as JAR
cd build && jar cf ../dataforge.jar io/ && cd ..

Java 25 Features Used

  • RecordsValidationError as an immutable data carrier
  • Sealed types ready — NodeType enum for exhaustive pattern matching
  • Pattern matchingswitch expressions with arrow syntax
  • Switch expressions — Throughout parsers, writers, and facade
  • Text blocks — Multi-line strings in tests and YAML configs
  • SequencedCollectionsSequencedMap for ordered XML attributes
  • Enhanced OptionalifPresentOrElse, fluent chains
  • String.formatted() — Modern string formatting
  • List.of(), toList() — Immutable collection factories

License

MIT

About

Data Forge Library to parse XML and JSON using only JAVA with no external libraries

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages