#json #json-parser #formatter #serialization #parser #convert-json #fixer

json-fixer

A robust library for fixing and formatting malformed JSON with support for type conversion

1 unstable release

0.1.0 Jan 22, 2025

#579 in Parser implementations

Download history 66/week @ 2025-01-16 52/week @ 2025-01-23 2/week @ 2025-01-30 6/week @ 2025-02-06

126 downloads per month

MIT license

68KB
1.5K SLoC

JSON Fixer

A robust Rust library for parsing and fixing malformed JSON. This library helps you handle common JSON formatting issues while maintaining the original data structure.

Features

  • Fixes common JSON formatting issues:
    • Unquoted object keys
    • Missing commas in objects and arrays
    • Trailing commas
    • Single-quoted strings
    • Simple syntax errors
    • Closes unclosed brackets and braces
  • Formatting options:
    • Pretty printing with customizable indentation
    • Space between keys and values
    • Preserve original formatting
    • Sort object keys alphabetically
  • Detailed error reporting with line and column information
  • Support for all JSON data types
  • Proper handling of escape sequences
  • Serde integration for type conversion (optional feature)
  • No external dependencies (unless using serde features)

Installation

Add this to your Cargo.toml:

[dependencies]
json-fixer = "0.1.0"  # Basic functionality
# Or with serde support:
json-fixer = { version = "0.1.0", features = ["serde"] }

Usage

Basic JSON Fixing

use json_fixer::JsonFixer;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Example of fixing malformed JSON
    let input = r#"{
        name: 'John'
        age: 30
        hobbies: ['reading' 'coding']
    }"#;
    
    // Using default configuration
    let fixed_json = JsonFixer::fix(input)?;
    println!("Fixed JSON: {}", fixed_json);
    // Result: {"name":"John","age":30,"hobbies":["reading","coding"]}
    
    Ok(())
}

Formatting Options

use json_fixer::{JsonFixer, JsonFixerConfig};

// Pretty printing
let pretty_json = JsonFixer::fix_pretty(input)?;
// Result:
// {
//     "name": "John",
//     "age": 30,
//     "hobbies": [
//         "reading",
//         "coding"
//     ]
// }

// Add spaces between keys and values
let spaced_json = JsonFixer::fix_with_space_between(input)?;
// Result: { "name": "John", "age": 30, "hobbies": ["reading", "coding"] }

// Custom configuration
let mut config = JsonFixerConfig::default();
config.sort_keys = true;
config.indent_size = 2;
let custom_json = JsonFixer::fix_with_config(input, config)?;

Serde Integration

When enabled with the serde feature, you can convert between JSON and Rust types:

use json_fixer::JsonFixer;
use serde::{Deserialize, Serialize};

#[derive(Deserialize, Serialize, Debug)]
struct Person {
    name: String,
    age: u32,
    hobbies: Vec<String>,
}

// Parse malformed JSON directly into a type
let input = r#"{ name: 'John', age: 30, hobbies: ['reading' 'coding'] }"#;
let person: Person = JsonFixer::from_fixed(input, None)?;

// Convert a type to properly formatted JSON
let json_string = JsonFixer::to_json(&person, None)?;

// Parse valid JSON into a type
let valid_json = r#"{"name":"John","age":30,"hobbies":["reading","coding"]}"#;
let person: Person = JsonFixer::from_str(valid_json)?;

Error Handling

The library provides detailed error information through the JsonFixerError enum:

pub enum JsonFixerError {
    Syntax(SyntaxError),
    Format(JsonFormatError),
    IO(std::fmt::Error),
    #[cfg(feature = "serde")]
    SerdeError(String),
}

pub enum SyntaxError {
    UnexpectedCharacter(char, Position),
    UnmatchedQuotes(Position),
    UnexpectedEndOfInput(Position),
    MissingComma(Position),
    InvalidNumber(String, Position),
    UnexpectedToken(String, Position),
}

pub enum JsonFormatError {
    LineTooLong {
        line: usize,
        length: usize,
        max: usize,
    },
    InvalidIndentation {
        line: usize,
    },
}

Examples

Fixing Missing Commas

// In arrays
let input = r#"[1 2 3 4]"#;
let fixed = JsonFixer::fix(input)?;
// Result: [1,2,3,4]

// In objects
let input = r#"{
    name: "Hicham-dine"
    age: 36
    job: "programmer"
}"#;
let fixed = JsonFixer::fix(input)?;
// Result: {"name":"Hicham-dine","age":36,"job":"programmer"}

Sorting Object Keys

let input = r#"{
    c: 3,
    a: 1,
    b: 2
}"#;
let mut config = JsonFixerConfig::default();
config.sort_keys = true;
let fixed = JsonFixer::fix_with_config(input, config)?;
// Result: {"a":1,"b":2,"c":3}

License

This project is licensed under the MIT License - see the LICENSE file for details.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

TODOs and Future Improvements

  • Full Support for JSON5 features
  • Streaming input support
  • Performance optimizations

Documentation

Full documentation is available at docs.rs.

Dependencies

~0–285KB