Repository: not-fl3/nanoserde (rust)

Issue:
JSONC (JSON with comments) support
It would be great if this was implemented. All that really needs to be done is that comments (`//` and `/* */`) should be ignored.

https://github.com/stephenberry/JSONC

I may try to implement this myself an open a PR. Would something like that be accepted?

Pull request description:
Add comment support in JSON (jsonc)
Closes #94. This PR adds comment support in the JSON parser. Comments are now ignored instead of causing an error. This should have no effect on valid JSON and adds virtually no overhead.

```jsonc
{
    "a": "b" // inline
    // single line
    /* multi
         line */
}
```

I have added 4 relevant tests and would appreciate if someone would test some more edge cases I didn't think of.

Patch:
diff --git a/src/serde_json.rs b/src/serde_json.rs
index d59e7ad..6f3139e 100644
--- a/src/serde_json.rs
+++ b/src/serde_json.rs
@@ -432,6 +432,35 @@ impl DeJsonState {
             self.tok = DeJsonTok::Eof;
             return Ok(());
         }
+        if self.cur == '/' {
+            self.next(i);
+            match self.cur {
+                '/' => {
+                    while self.cur != '\n' && self.cur != '\0' {
+                        self.next(i);
+                    }
+                    return self.next_tok(i);
+                }
+                '*' => {
+                    let mut last = self.cur;
+                    loop {
+                        self.next(i);
+                        if self.cur == '\0' {
+                            return Err(self.err_token("MultiLineCommentClose"));
+                        }
+                        if last == '*' && self.cur == '/' {
+                            self.next(i);
+                            break;
+                        }
+                        last = self.cur;
+                    }
+                    return self.next_tok(i);
+                }
+                _ => {
+                    return Err(self.err_token("CommentOpen"));
+                }
+            }
+        }
         match self.cur {
             ':' => {
                 self.next(i);


Test patch:
diff --git a/tests/json.rs b/tests/json.rs
index 5622f60..41ce1b1 100644
--- a/tests/json.rs
+++ b/tests/json.rs
@@ -34,6 +34,90 @@ fn de() {
     assert_eq!(test.c, None);
 }
 
+#[test]
+fn de_inline_comment() {
+    #[derive(DeJson)]
+    pub struct Test {
+        pub a: Option<String>,
+    }
+
+    let json = r#"{ //comment
+        // comment
+        "a": "// asd"// comment
+    } // comment"#;
+
+    let test: Test = DeJson::deserialize_json(json).unwrap();
+    assert_eq!(test.a.unwrap(), "// asd");
+}
+
+#[test]
+fn de_multiline_comment() {
+    #[derive(DeJson)]
+    pub struct Test {
+        pub a: f32,
+    }
+
+    let json = r#"{ /* multiline
+        comment */
+        "a": 1 /* multiline *
+        comment */
+    } /** multiline **/"#;
+
+    let test: Test = DeJson::deserialize_json(json).unwrap();
+    assert_eq!(test.a, 1.);
+}
+
+#[test]
+fn de_illegal_inline_comment() {
+    #[derive(DeJson)]
+    pub struct Test {
+        pub a: f32,
+    }
+
+    let jsons = vec![
+        r#"{
+            "a": // comment,
+        }"#,
+        r#"{
+            / comment
+            "a": 1,
+        }"#,
+    ];
+
+    for json in jsons {
+        let test: Result<Test, _> = DeJson::deserialize_json(json);
+        assert!(test.is_err());
+    }
+}
+
+#[test]
+fn de_illegal_multiline_comment() {
+    #[derive(DeJson)]
+    pub struct Test {
+        pub a: f32,
+    }
+
+    let jsons = vec![
+        r#"{
+            /* /* comment */ */
+            "a": 1
+        }"#,
+        r#"{
+            /* comment
+            "a": 1
+        }"#,
+        r#"{
+            */
+            "a": 1
+        }"#,
+    ];
+
+    for json in jsons {
+        let test: Result<Test, _> = DeJson::deserialize_json(json);
+        assert!(test.is_err());
+    }
+}
+
 #[test]
 fn de_reorder() {
     #[derive(DeJson)]