-
-
Notifications
You must be signed in to change notification settings - Fork 284
Add JSON marshaling library #2255
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
- Add json_marshal.c3 with Go-style API (json::marshal, json::marshal_value, json::marshal_array) - Support all primitive types: String, int, float, double, bool - Support enums (always marshaled as enum names, regardless of associated values) - Support nested structs and arrays of any supported type - Use temp allocator for memory-safe operation - Comprehensive test suite with 15 test cases covering all features - Follow C3 coding style with proper and kindof usage
I think that |
- Extract common marshaling logic into marshal_value function - Simplify marshal() to use marshal_value for all struct fields - Simplify marshal_array() to use marshal_value for all array elements - Add array/slice support to marshal_value function - Reduce code duplication by ~60 lines while maintaining all functionality - All existing tests continue to pass
serialization and deserialization are too long for a function name, IMHO. I'd prefer shorter name like, marshal/unmarshal, like in golang. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While I do not have any power over merging PRs, I went ahead and looked at the code.
The naming issue aside (I also prefer serialize
/deserialize
), the code seems to be written in a weird way. You claim to follow the C3 coding style, but the use of doc-comments and optionals is just plain different (and in case of doc-comments just wrong) from what the rest of the standard library uses.
If you're serious about getting this working and up to standards, feel free to join the Discord to chat about improving this. (Discord link: https://discord.gg/qN76R87, can also be found on the C3 website.)
lib/std/encoding/json_marshal.c3
Outdated
/** | ||
* Marshal a struct with primitive fields and nested structs to JSON | ||
* @param [in] value The struct value to marshal | ||
* @return The JSON string representation (using temp allocator) | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doc-comments are written with <* *>
in C3.
<*
Marshal a struct with primitive fields and nested structs to JSON
@param [in] value The struct value to marshal
@return The JSON string representation (using temp allocator)
*>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
lib/std/encoding/json_marshal.c3
Outdated
// Only handle structs | ||
$if $Type.kindof != STRUCT: | ||
return UNSUPPORTED_TYPE?; | ||
$endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the kind of thing you put as an @require
in the doc-contract.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
lib/std/encoding/json_marshal.c3
Outdated
return UNSUPPORTED_TYPE?; | ||
$endif | ||
|
||
DString result = dstring::temp(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using temp allocator not in a @pool
and then return a string-view to it?
While this might work because it's a macro, it feels wrong, especially because the macro-name does not signify that any allocations would happen that can have an influence outside this function.
Take a look at how String.escape
is handled in core/string_escape.c3
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed, adding an allocator as input
lib/std/encoding/json_marshal.c3
Outdated
String? field_result = marshal_value($member.get(value)); | ||
if (catch err = field_result) return err?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'd write this as:
String field_result = marshal_value($member.get(value))!;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
String? result = json::marshal_value(42); | ||
assert(result!! == "42"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be better to write
String result = json::marshal_value(42)!!;
assert(result == "42");
Idem for all other tests btw.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
assert(json.contains(`"complex_state":"BUSY"`)); // Always uses enum name | ||
assert(json.contains(`"pid":1234`)); | ||
|
||
// Should be valid JSON format |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Testing if it's actually valid JSON is not 100% covered here, it might be worth writing a small checking function that will check if all keys are in quotes, that key-value pairs are seperated by :
, that there are commas where needed...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed, now using json::tparse to parse the json, and verify the result.
Sorry about the that, most of the code and docs are written by AI, both AI and myself are still learning how to writing c3 code properly. Thanks for your feedback, all are addressed. I will join Discord soon. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know how I feel knowing this is done using AI. I feel like it's weird to jump into an open-source project and start letting AI make contributions. To me I'd feel like I want to do contrib 6D47 utions myself to learn the language and become fluid in it.
On the other hand the implementation seems ok.
But this is the last you'll hear from me about this I think, the rest is for @lerno to decide.
result.append(field_result); | ||
}; | ||
$endif | ||
$endforeach | ||
|
||
result.append_char('}'); | ||
return result.str_view(); | ||
return result.copy_str(allocator); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not deallocating the DString will leak memory, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed, finally figured out how to use pool and tmem
Object* parsed = json::tparse_string(json)!!; | ||
defer parsed.free(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're using the temp allocator, no need to free that explicitly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
lib/std/encoding/json_marshal.c3
Outdated
@param allocator : "The allocator to use for the result" | ||
@param value: "The struct value to marshal" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
inconsistent spaces around the :
, it seems to be inconsistent in almost every doc-string.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
While I use AI to generate code and documentation, I am still a significant contributor to the final code. It takes considerable effort—often an hour or more—to guide the AI to write correct code. Because there is very little C3 code available for training, the AI's knowledge of the language is limited, which requires a lot of manual guidance to get it working correctly. |
I don't have a set opinion on AI. However, any non-trivial feature should currently be incubated before inclusion. So the process is this:
|
Are you alright with closing this @sudison and offering it through the regular process of an incubator? |
Refer to request: #1395