mirror of
https://github.com/Noratrieb/jsonformat.git
synced 2026-01-14 14:15:03 +01:00
works
This commit is contained in:
parent
bf1155cd00
commit
d0733b1a7c
4 changed files with 181 additions and 3 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
|
@ -1,3 +1,6 @@
|
||||||
/target
|
/target
|
||||||
.idea
|
.idea
|
||||||
*.iml
|
*.iml
|
||||||
|
|
||||||
|
# test data
|
||||||
|
*.json
|
||||||
7
README.md
Normal file
7
README.md
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
Formats json.
|
||||||
|
|
||||||
|
Will maybe even be fast in the future, idk
|
||||||
|
|
||||||
|
would be amazing if it even works.
|
||||||
|
|
||||||
|
note: does not actually parse the json to a parse tree or something, it just formats it
|
||||||
149
src/lib.rs
Normal file
149
src/lib.rs
Normal file
|
|
@ -0,0 +1,149 @@
|
||||||
|
pub fn format_json(json: &str, indent_str: &str) -> String {
|
||||||
|
let mut out = String::with_capacity(json.len()); // at least as big as the input
|
||||||
|
|
||||||
|
let mut escaped = false;
|
||||||
|
let mut in_string = false;
|
||||||
|
let mut indent_level = 0;
|
||||||
|
let mut newline_requested = false; // invalidated if next character is ] or }
|
||||||
|
|
||||||
|
for char in json.chars() {
|
||||||
|
if in_string {
|
||||||
|
let mut escape_here = false;
|
||||||
|
match char {
|
||||||
|
'"' => {
|
||||||
|
if !escaped {
|
||||||
|
in_string = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'\\' => {
|
||||||
|
if !escaped {
|
||||||
|
escape_here = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
out.push(char);
|
||||||
|
escaped = escape_here;
|
||||||
|
} else {
|
||||||
|
let mut auto_push = true;
|
||||||
|
let mut request_newline = false;
|
||||||
|
let old_level = indent_level;
|
||||||
|
match char {
|
||||||
|
'"' => in_string = true,
|
||||||
|
' ' | '\n' | '\t' => continue,
|
||||||
|
'[' => {
|
||||||
|
indent_level += 1;
|
||||||
|
request_newline = true;
|
||||||
|
}
|
||||||
|
'{' => {
|
||||||
|
indent_level += 1;
|
||||||
|
request_newline = true;
|
||||||
|
}
|
||||||
|
'}' | ']' => {
|
||||||
|
indent_level -= 1;
|
||||||
|
if !newline_requested {
|
||||||
|
// see comment above
|
||||||
|
out.push('\n');
|
||||||
|
indent(&mut out, indent_level, indent_str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
':' => {
|
||||||
|
auto_push = false;
|
||||||
|
out.push(char);
|
||||||
|
out.push(' ');
|
||||||
|
}
|
||||||
|
',' => {
|
||||||
|
request_newline = true;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
if newline_requested && char != ']' && char != '}' {
|
||||||
|
// newline only happens after { [ and ,
|
||||||
|
out.push('\n');
|
||||||
|
indent(&mut out, old_level, indent_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
if auto_push {
|
||||||
|
out.push(char);
|
||||||
|
}
|
||||||
|
|
||||||
|
newline_requested = request_newline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out
|
||||||
|
}
|
||||||
|
|
||||||
|
fn indent(buf: &mut String, level: usize, indent_str: &str) {
|
||||||
|
for _ in 0..level {
|
||||||
|
buf.push_str(indent_str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
const INDENT: &str = " ";
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn echoes_primitive() {
|
||||||
|
let json = "1.35";
|
||||||
|
assert_eq!(json, format_json(json, INDENT));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ignore_whitespace_in_string() {
|
||||||
|
let json = "\" hallo \"";
|
||||||
|
assert_eq!(json, format_json(json, INDENT));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn remove_leading_whitespace() {
|
||||||
|
let json = " 0";
|
||||||
|
let expected = "0";
|
||||||
|
assert_eq!(expected, format_json(json, INDENT));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn handle_escaped_strings() {
|
||||||
|
let json = " \" hallo \\\" \" ";
|
||||||
|
let expected = "\" hallo \\\" \"";
|
||||||
|
assert_eq!(expected, format_json(json, INDENT));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn simple_object() {
|
||||||
|
let json = "{\"a\":0}";
|
||||||
|
let expected = "{
|
||||||
|
\"a\": 0
|
||||||
|
}";
|
||||||
|
assert_eq!(expected, format_json(json, INDENT));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn simple_array() {
|
||||||
|
let json = "[1,2,null]";
|
||||||
|
let expected = "[
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
null
|
||||||
|
]";
|
||||||
|
assert_eq!(expected, format_json(json, INDENT));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn array_of_object() {
|
||||||
|
let json = "[{\"a\": 0}, {}, {\"a\": null}]";
|
||||||
|
let expected = "[
|
||||||
|
{
|
||||||
|
\"a\": 0
|
||||||
|
},
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
\"a\": null
|
||||||
|
}
|
||||||
|
]";
|
||||||
|
|
||||||
|
assert_eq!(expected, format_json(json, INDENT));
|
||||||
|
}
|
||||||
|
}
|
||||||
23
src/main.rs
23
src/main.rs
|
|
@ -1,3 +1,22 @@
|
||||||
fn main() {
|
use jsonformat::format_json;
|
||||||
println!("Hello, world!");
|
use std::fs;
|
||||||
|
use std::io;
|
||||||
|
use std::io::Read;
|
||||||
|
|
||||||
|
fn main() -> Result<(), io::Error> {
|
||||||
|
let filename = std::env::args().skip(1).next();
|
||||||
|
|
||||||
|
let str = match filename {
|
||||||
|
Some(path) => fs::read_to_string(path)?,
|
||||||
|
None => {
|
||||||
|
let mut buf = String::new();
|
||||||
|
let stdin = std::io::stdin();
|
||||||
|
stdin.lock().read_to_string(&mut buf)?;
|
||||||
|
buf
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
println!("{}", format_json(&str, " "));
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue