Thanks to visit codestin.com
Credit goes to lib.rs

14 releases

Uses new Rust 2024

0.3.6 Sep 4, 2025
0.3.5 Aug 30, 2025
0.3.2 Jul 28, 2025
0.2.2 Jul 14, 2025
0.1.2 Apr 8, 2025

#207 in Encoding

Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App

4,507 downloads per month
Used in 12 crates

MIT license

125KB
2.5K SLoC

nojson

nojson Documentation Actions Status License

A flexible Rust JSON library with no dependencies and no macros.

nojson is a flexible and ergonomic JSON library for Rust that offers a balance between the type-safety of Rust and the dynamic nature of JSON. Unlike serde, which typically requires one-to-one mapping between Rust types and JSON structures (or other serialization formats), nojson provides a toolbox approach that allows you to leverage both type-level programming and imperative code flexibility.

Features

  • No strict one-to-one type mapping required - Mix type-level programming with imperative flexibility as needed
  • Clean parsing error messages with position information for better debugging
  • Customizable validation - Add application-specific validation rules with proper error context
  • Flexible formatting options including pretty-printing with customizable indentation
  • Low-level access to the JSON structure when needed
  • High-level conveniences for common JSON operations

Core Design Principles

  • A toolbox rather than a monolithic framework
  • Gain the benefits of both type-level programming and imperative code
  • Easy to add custom validations with rich error context
  • Error messages that precisely indicate the problematic position in the JSON text

Getting Started

Parsing JSON with Strong Typing

The Json<T> wrapper allows parsing JSON text into Rust types that implement TryFrom<RawJsonValue<'_, '_>>:

use nojson::Json;

fn main() -> Result<(), nojson::JsonParseError> {
    // Parse a JSON array into a typed Rust array
    let text = "[1, null, 2]";
    let value: Json<[Option<u32>; 3]> = text.parse()?;
    assert_eq!(value.0, [Some(1), None, Some(2)]);
    Ok(())
}

Generating JSON

The DisplayJson trait allows converting Rust types to JSON:

use nojson::Json;

// Generate a JSON array from a Rust array
let value = [Some(1), None, Some(2)];
assert_eq!(Json(value).to_string(), "[1,null,2]");

In-place JSON Generation with Formatting

The json() function provides a convenient way to generate JSON with custom formatting:

use nojson::json;

// Compact JSON
let compact = json(|f| f.value([1, 2, 3]));
assert_eq!(compact.to_string(), "[1,2,3]");

// Pretty-printed JSON with custom indentation
let pretty = json(|f| {
    f.set_indent_size(2);
    f.set_spacing(true);
    f.array(|f| {
        f.element(1)?;
        f.element(2)?;
        f.element(3)
    })
});

assert_eq!(
    format!("\n{}", pretty),
    r#"
[
  1,
  2,
  3
]"#
);

Custom Types

Implementing DisplayJson and TryFrom<RawJsonValue<'_, '_>> for your own types:

use nojson::{DisplayJson, Json, JsonFormatter, JsonParseError, RawJsonValue};

struct Person {
    name: String,
    age: u32,
}

impl DisplayJson for Person {
    fn fmt(&self, f: &mut JsonFormatter<'_, '_>) -> std::fmt::Result {
        f.object(|f| {
            f.member("name", &self.name)?;
            f.member("age", self.age)
        })
    }
}

impl<'text, 'raw> TryFrom<RawJsonValue<'text, 'raw>> for Person {
    type Error = JsonParseError;

    fn try_from(value: RawJsonValue<'text, 'raw>) -> Result<Self, Self::Error> {
        let name = value.to_member("name")?.required()?;
        let age = value.to_member("age")?.required()?;
        Ok(Person {
            name: name.try_into()?,
            age: age.try_into()?,
        })
    }
}

fn main() -> Result<(), JsonParseError> {
    // Parse JSON to Person
    let json_text = r#"{"name":"Alice","age":30}"#;
    let person: Json<Person> = json_text.parse()?;

    // Generate JSON from Person
    assert_eq!(Json(&person.0).to_string(), json_text);

    Ok(())
}

Advanced Features

Custom Validations

You can add custom validations using RawJsonValue::invalid():

use nojson::{JsonParseError, RawJson, RawJsonValue};

fn parse_positive_number(text: &str) -> Result<u32, JsonParseError> {
    let json = RawJson::parse(text)?;
    let raw_value = json.value();

    let num: u32 = raw_value.as_number_str()?
        .parse()
        .map_err(|e| raw_value.invalid(e))?;

    if num == 0 {
        return Err(raw_value.invalid("Expected a positive number, got 0"));
    }

    Ok(num)
}

Error Handling with Context

Rich error information helps with debugging:

use nojson::{JsonParseError, RawJson};

let text = r#"{"invalid": 123e++}"#;
let result = RawJson::parse(text);

if let Err(error) = result {
    println!("Error: {}", error);

    // Get line and column information
    if let Some((line, column)) = error.get_line_and_column_numbers(text) {
        println!("At line {}, column {}", line, column);
    }

    // Get the full line with the error
    if let Some(line_text) = error.get_line(text) {
        println!("Line content: {}", line_text);
    }
}

No runtime deps