aboutsummaryrefslogtreecommitdiff
path: root/core/encoding
diff options
context:
space:
mode:
authorLaytan <laytanlaats@hotmail.com>2025-05-15 22:31:34 +0200
committerGitHub <noreply@github.com>2025-05-15 22:31:34 +0200
commitd3159f74cd3fccbb345f4f857f3320e6b364d474 (patch)
treec10774148c8ae0304a3478c912cd9f66629be7ff /core/encoding
parent2f636886a565c113840d8e0b81454a24c6f7b9a0 (diff)
parent3148acf6a69868ddec0780daa293866fe079b7d4 (diff)
Merge pull request #4944 from dozn/master
[core:encoding/json] When Unmarshalling, Only Match On Struct Tags If Present
Diffstat (limited to 'core/encoding')
-rw-r--r--core/encoding/json/unmarshal.odin22
1 files changed, 14 insertions, 8 deletions
diff --git a/core/encoding/json/unmarshal.odin b/core/encoding/json/unmarshal.odin
index 151bd69c3..b9ed1476f 100644
--- a/core/encoding/json/unmarshal.odin
+++ b/core/encoding/json/unmarshal.odin
@@ -406,6 +406,9 @@ unmarshal_expect_token :: proc(p: ^Parser, kind: Token_Kind, loc := #caller_loca
return prev
}
+// Struct tags can include not only the name of the JSON key, but also a tag such as `omitempty`.
+// Example: `json:"key_name,omitempty"`
+// This returns the first field as `json_name`, and the rest are returned as `extra`.
@(private)
json_name_from_tag_value :: proc(value: string) -> (json_name, extra: string) {
json_name = value
@@ -441,12 +444,6 @@ unmarshal_object :: proc(p: ^Parser, v: any, end_token: Token_Kind) -> (err: Unm
defer delete(key, p.allocator)
unmarshal_expect_token(p, .Colon)
-
- field_test :: #force_inline proc "contextless" (field_used: [^]byte, offset: uintptr) -> bool {
- prev_set := field_used[offset/8] & byte(offset&7) != 0
- field_used[offset/8] |= byte(offset&7)
- return prev_set
- }
field_used_bytes := (reflect.size_of_typeid(ti.id)+7)/8
field_used := intrinsics.alloca(field_used_bytes + 1, 1) // + 1 to not overflow on size_of 0 types.
@@ -465,7 +462,9 @@ unmarshal_object :: proc(p: ^Parser, v: any, end_token: Token_Kind) -> (err: Unm
if use_field_idx < 0 {
for field, field_idx in fields {
- if key == field.name {
+ tag_value := reflect.struct_tag_get(field.tag, "json")
+ json_name, _ := json_name_from_tag_value(tag_value)
+ if json_name == "" && key == field.name {
use_field_idx = field_idx
break
}
@@ -486,7 +485,9 @@ unmarshal_object :: proc(p: ^Parser, v: any, end_token: Token_Kind) -> (err: Unm
}
}
- if field.name == key || (field.tag != "" && reflect.struct_tag_get(field.tag, "json") == key) {
+ tag_value := reflect.struct_tag_get(field.tag, "json")
+ json_name, _ := json_name_from_tag_value(tag_value)
+ if (json_name == "" && field.name == key) || json_name == key {
offset = field.offset
type = field.type
found = true
@@ -508,6 +509,11 @@ unmarshal_object :: proc(p: ^Parser, v: any, end_token: Token_Kind) -> (err: Unm
}
if field_found {
+ field_test :: #force_inline proc "contextless" (field_used: [^]byte, offset: uintptr) -> bool {
+ prev_set := field_used[offset/8] & byte(offset&7) != 0
+ field_used[offset/8] |= byte(offset&7)
+ return prev_set
+ }
if field_test(field_used, offset) {
return .Multiple_Use_Field
}