✨ Add support for mixed-level nested keys with dot/blank handling
- Handle @parent:child and @parent🧒grandchild coexistence
- Use '.' key for parent values when nested children exist
- Add comprehensive test cases for double-nested scenarios
- Support both '.' and '' as special keys for parent values
This commit is contained in:
parent
44ecfd6ac9
commit
6095c2497e
3 changed files with 53 additions and 5 deletions
|
|
@ -88,6 +88,24 @@ func TestEntryMarshal(t *testing.T) {
|
||||||
[]string{"@me:age 43", "@me:name:first Dan", "@me:name:last Jones"},
|
[]string{"@me:age 43", "@me:name:first Dan", "@me:name:last Jones"},
|
||||||
nil,
|
nil,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"double-nested-map-dot",
|
||||||
|
"Title DM",
|
||||||
|
when,
|
||||||
|
[]Meta{{"me", map[string]any{"age": 43, "name": map[string]any{".": "Dan Jones", "nick": "Danny"}}}},
|
||||||
|
"@begin " + whens + " - Title DM",
|
||||||
|
[]string{"@me:age 43", "@me:name Dan Jones", "@me:name:nick Danny"},
|
||||||
|
nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"double-nested-map-blank",
|
||||||
|
"Title DM",
|
||||||
|
when,
|
||||||
|
[]Meta{{"me", map[string]any{"age": 43, "name": map[string]any{"": "Dan Jones", "nick": "Danny"}}}},
|
||||||
|
"@begin " + whens + " - Title DM",
|
||||||
|
[]string{"@me:age 43", "@me:name Dan Jones", "@me:name:nick Danny"},
|
||||||
|
nil,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"nested-keys-in-json",
|
"nested-keys-in-json",
|
||||||
"Title NKJ",
|
"Title NKJ",
|
||||||
|
|
@ -169,6 +187,14 @@ func TestEntryUnmarshal(t *testing.T) {
|
||||||
[]Meta{{"me:name", "Dan"}, {"me:coder", true}},
|
[]Meta{{"me:name", "Dan"}, {"me:coder", true}},
|
||||||
nil,
|
nil,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"nested-field-dot",
|
||||||
|
"@begin " + whens + " - A Title\n@me:name Dan Jones\n@me:name:nick Danny\n@me:coder true @end",
|
||||||
|
"A Title",
|
||||||
|
when,
|
||||||
|
[]Meta{{"me:name", "Dan Jones"}, {"me:name:nick", "Danny"}, {"me:coder", true}},
|
||||||
|
nil,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"json-field",
|
"json-field",
|
||||||
"@begin " + whens + " - Some Guy\n" + `@json {"name":"Dan","coder":true} @end`,
|
"@begin " + whens + " - Some Guy\n" + `@json {"name":"Dan","coder":true} @end`,
|
||||||
|
|
@ -256,6 +282,9 @@ func TestEntryJsonMarshal(t *testing.T) {
|
||||||
{"nested-field", "A Title", when, []Meta{{"obj:foo", "bar"}, {"obj:title", "Sub-title"}}, `{"title":"A Title","date":"` + whens + `","obj":{"foo":"bar","title":"Sub-title"}}`, nil},
|
{"nested-field", "A Title", when, []Meta{{"obj:foo", "bar"}, {"obj:title", "Sub-title"}}, `{"title":"A Title","date":"` + whens + `","obj":{"foo":"bar","title":"Sub-title"}}`, nil},
|
||||||
{"double-nested-field", "A Title", when, []Meta{{"obj:foo", "bar"}, {"obj:me:name", "Dan"}, {"obj:me:age", 27}}, `{"title":"A Title","date":"` + whens + `","obj":{"foo":"bar","me":{"name":"Dan","age":27}}}`, nil},
|
{"double-nested-field", "A Title", when, []Meta{{"obj:foo", "bar"}, {"obj:me:name", "Dan"}, {"obj:me:age", 27}}, `{"title":"A Title","date":"` + whens + `","obj":{"foo":"bar","me":{"name":"Dan","age":27}}}`, nil},
|
||||||
{"nested-plus-json", "A Title", when, []Meta{{"obj:foo", "bar"}, {"obj:me", json.RawMessage(`{"name":"Dan","age":27}`)}}, `{"title":"A Title","date":"` + whens + `","obj":{"foo":"bar","me":{"name":"Dan","age":27}}}`, nil},
|
{"nested-plus-json", "A Title", when, []Meta{{"obj:foo", "bar"}, {"obj:me", json.RawMessage(`{"name":"Dan","age":27}`)}}, `{"title":"A Title","date":"` + whens + `","obj":{"foo":"bar","me":{"name":"Dan","age":27}}}`, nil},
|
||||||
|
{"nested-part", "A Title", when, []Meta{{"obj:foo", "bar"}, {"obj:me", "Dan"}, {"obj:me:age", 27}}, `{"title":"A Title","date":"` + whens + `","obj":{"foo":"bar","me":{".":"Dan","age":27}}}`, nil},
|
||||||
|
{"nested-part-order", "A Title", when, []Meta{{"obj:foo", "bar"}, {"obj:me:age", 27}, {"obj:me", "Dan"}}, `{"title":"A Title","date":"` + whens + `","obj":{"foo":"bar","me":{".":"Dan","age":27}}}`, nil},
|
||||||
|
{"nested-part-order-two", "A Title", when, []Meta{{"obj:foo", "bar"}, {"obj:me:age", 27}, {"obj:me", "Dan"}, {"obj:me:cool", true}}, `{"title":"A Title","date":"` + whens + `","obj":{"foo":"bar","me":{".":"Dan","age":27,"cool":true}}}`, nil},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
|
|
||||||
|
|
@ -50,12 +50,16 @@ func marshalMap(pre string, mp map[string]any, buff *bytes.Buffer) error {
|
||||||
buff.WriteRune('\n')
|
buff.WriteRune('\n')
|
||||||
}
|
}
|
||||||
idx++
|
idx++
|
||||||
|
newKey := pre + ":" + k
|
||||||
|
if k == "." || k == "" {
|
||||||
|
newKey = pre
|
||||||
|
}
|
||||||
if subM, ok := v.(map[string]any); ok {
|
if subM, ok := v.(map[string]any); ok {
|
||||||
if err := marshalMap(pre+":"+k, subM, buff); err != nil {
|
if err := marshalMap(newKey, subM, buff); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mSub := Meta{pre + ":" + k, v}
|
mSub := Meta{newKey, v}
|
||||||
if err := mSub.marshalToBuff(buff); err != nil {
|
if err := mSub.marshalToBuff(buff); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ func (ms Metas) Map() map[string]any {
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseNestedFields(f map[string]any) {
|
func parseNestedFields(f map[string]any) {
|
||||||
|
todelete := make([]string, 0, len(f))
|
||||||
for k, v := range f {
|
for k, v := range f {
|
||||||
if strings.Contains(k, ":") {
|
if strings.Contains(k, ":") {
|
||||||
idx := strings.Index(k, ":")
|
idx := strings.Index(k, ":")
|
||||||
|
|
@ -50,14 +51,28 @@ func parseNestedFields(f map[string]any) {
|
||||||
|
|
||||||
nest, ok := f[top].(map[string]any)
|
nest, ok := f[top].(map[string]any)
|
||||||
if !ok {
|
if !ok {
|
||||||
nest = map[string]any{}
|
curr := f[top]
|
||||||
|
if curr == nil {
|
||||||
|
nest = map[string]any{}
|
||||||
|
} else {
|
||||||
|
nest = map[string]any{".": curr}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
curr, ok := nest[bottom].(map[string]any)
|
||||||
|
if ok {
|
||||||
|
curr["."] = v
|
||||||
|
} else {
|
||||||
|
nest[bottom] = v
|
||||||
}
|
}
|
||||||
nest[bottom] = v
|
|
||||||
parseNestedFields(nest)
|
parseNestedFields(nest)
|
||||||
f[top] = nest
|
f[top] = nest
|
||||||
delete(f, k)
|
todelete = append(todelete, k)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for _, k := range todelete {
|
||||||
|
delete(f, k)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements json.Marshaler
|
// Implements json.Marshaler
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue