Skip to content

Commit 3148acf

Browse files
committed
[core:encoding/json] When Unmarshalling, Only Match Struct Tags If Present
1 parent 0c70ec0 commit 3148acf

File tree

1 file changed

+14
-8
lines changed

1 file changed

+14
-8
lines changed

core/encoding/json/unmarshal.odin

+14-8
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,9 @@ unmarshal_expect_token :: proc(p: ^Parser, kind: Token_Kind, loc := #caller_loca
390390
return prev
391391
}
392392

393+
// Struct tags can include not only the name of the JSON key, but also a tag such as `omitempty`.
394+
// Example: `json:"key_name,omitempty"`
395+
// This returns the first field as `json_name`, and the rest are returned as `extra`.
393396
@(private)
394397
json_name_from_tag_value :: proc(value: string) -> (json_name, extra: string) {
395398
json_name = value
@@ -425,12 +428,6 @@ unmarshal_object :: proc(p: ^Parser, v: any, end_token: Token_Kind) -> (err: Unm
425428
defer delete(key, p.allocator)
426429

427430
unmarshal_expect_token(p, .Colon)
428-
429-
field_test :: #force_inline proc "contextless" (field_used: [^]byte, offset: uintptr) -> bool {
430-
prev_set := field_used[offset/8] & byte(offset&7) != 0
431-
field_used[offset/8] |= byte(offset&7)
432-
return prev_set
433-
}
434431

435432
field_used_bytes := (reflect.size_of_typeid(ti.id)+7)/8
436433
field_used := intrinsics.alloca(field_used_bytes + 1, 1) // + 1 to not overflow on size_of 0 types.
@@ -449,7 +446,9 @@ unmarshal_object :: proc(p: ^Parser, v: any, end_token: Token_Kind) -> (err: Unm
449446

450447
if use_field_idx < 0 {
451448
for field, field_idx in fields {
452-
if key == field.name {
449+
tag_value := reflect.struct_tag_get(field.tag, "json")
450+
json_name, _ := json_name_from_tag_value(tag_value)
451+
if json_name == "" && key == field.name {
453452
use_field_idx = field_idx
454453
break
455454
}
@@ -470,7 +469,9 @@ unmarshal_object :: proc(p: ^Parser, v: any, end_token: Token_Kind) -> (err: Unm
470469
}
471470
}
472471

473-
if field.name == key || (field.tag != "" && reflect.struct_tag_get(field.tag, "json") == key) {
472+
tag_value := reflect.struct_tag_get(field.tag, "json")
473+
json_name, _ := json_name_from_tag_value(tag_value)
474+
if (json_name == "" && field.name == key) || json_name == key {
474475
offset = field.offset
475476
type = field.type
476477
found = true
@@ -492,6 +493,11 @@ unmarshal_object :: proc(p: ^Parser, v: any, end_token: Token_Kind) -> (err: Unm
492493
}
493494

494495
if field_found {
496+
field_test :: #force_inline proc "contextless" (field_used: [^]byte, offset: uintptr) -> bool {
497+
prev_set := field_used[offset/8] & byte(offset&7) != 0
498+
field_used[offset/8] |= byte(offset&7)
499+
return prev_set
500+
}
495501
if field_test(field_used, offset) {
496502
return .Multiple_Use_Field
497503
}

0 commit comments

Comments
 (0)