mirror of
https://github.com/therootcompany/golib.git
synced 2026-11-04 15:05:00 +00:00
feat(jsontypes): short raw paths — type name only on intro line
Type names now appear once on the intro line, and subsequent fields
use the bare path without repeating the type. Root no longer has a
leading dot.
Before: .{Root0}.rooms[]{RoomsItem1}._timing{Timing2}.account_ms{int}
After: .rooms[]._timing.account_ms{int}
The type intro line declares the type, making the path structure
cleaner and more readable while remaining lossless.
This commit is contained in:
parent
69d757bc69
commit
a346049cc4
@ -16,7 +16,7 @@ import (
|
||||
// integers and floats are distinguishable.
|
||||
func RawPaths(v any) []string {
|
||||
w := &rawWalker{}
|
||||
w.walk(".", v)
|
||||
w.walk("", v)
|
||||
return w.paths
|
||||
}
|
||||
|
||||
@ -31,20 +31,6 @@ func (w *rawWalker) emit(path string) {
|
||||
|
||||
func (w *rawWalker) nextName(path string) string {
|
||||
name := inferRawTypeName(path)
|
||||
|
||||
// If the inferred name matches a parent type in the path, prefix with
|
||||
// the parent to disambiguate. E.g., a "room" field under {Room1} would
|
||||
// infer "Room" — prefix it to "RoomRoom" so the reader knows it's the
|
||||
// child type, not the parent.
|
||||
parent := parentTypeName(path)
|
||||
if parent != "" {
|
||||
// Strip trailing digits from parent for comparison.
|
||||
parentBase := strings.TrimRight(parent, "0123456789")
|
||||
if parentBase == name {
|
||||
name = parentBase + name
|
||||
}
|
||||
}
|
||||
|
||||
id := w.counter
|
||||
w.counter++
|
||||
return fmt.Sprintf("%s%d", name, id)
|
||||
@ -101,11 +87,12 @@ func (w *rawWalker) walkMap(prefix string, obj map[string]any) {
|
||||
func (w *rawWalker) walkStruct(prefix string, instances []map[string]any) {
|
||||
merged := mergeObjects(instances)
|
||||
typeName := w.nextName(prefix)
|
||||
typePrefix := prefix + "{" + typeName + "}"
|
||||
|
||||
// Emit type intro.
|
||||
w.emit(typePrefix)
|
||||
// Emit type intro with the type name.
|
||||
w.emit(prefix + "{" + typeName + "}")
|
||||
|
||||
// Fields use the bare prefix (without the type name) since
|
||||
// the type was already declared on the intro line above.
|
||||
keys := sortedKeys(merged)
|
||||
for _, k := range keys {
|
||||
// Collect all values for this field across instances.
|
||||
@ -117,7 +104,7 @@ func (w *rawWalker) walkStruct(prefix string, instances []map[string]any) {
|
||||
fieldVals = append(fieldVals, nil)
|
||||
}
|
||||
}
|
||||
w.walkCollection(typePrefix+"."+k, fieldVals)
|
||||
w.walkCollection(joinPath(prefix, k), fieldVals)
|
||||
}
|
||||
}
|
||||
|
||||
@ -235,7 +222,7 @@ func (w *rawWalker) walkCollection(prefix string, values []any) {
|
||||
// Collection elements get "<Name>Item" (e.g., friends[] → FriendsItem).
|
||||
// Direct fields use PascalCase as-is (e.g., address → Address).
|
||||
func inferRawTypeName(path string) string {
|
||||
if path == "." {
|
||||
if path == "" {
|
||||
return "Root"
|
||||
}
|
||||
|
||||
@ -282,3 +269,10 @@ func inferRawTypeName(path string) string {
|
||||
return name
|
||||
}
|
||||
|
||||
// joinPath appends a field name to a path prefix with a dot separator.
|
||||
func joinPath(prefix, field string) string {
|
||||
if prefix == "" {
|
||||
return "." + field
|
||||
}
|
||||
return prefix + "." + field
|
||||
}
|
||||
|
||||
@ -20,11 +20,12 @@ func TestRawPathsFixtures(t *testing.T) {
|
||||
name: "pokemon",
|
||||
file: "testdata/pokemon-pikachu.json",
|
||||
mustContain: []string{
|
||||
".{Root0}.name{string}",
|
||||
".{Root0}.abilities[]{AbilitiesItem",
|
||||
".{Root0}.stats[]{StatsItem",
|
||||
".{Root0}.types[]{TypesItem",
|
||||
".{Root0}.sprites{Sprite",
|
||||
"{Root0}",
|
||||
".name{string}",
|
||||
".abilities[]{AbilitiesItem",
|
||||
".stats[]{StatsItem",
|
||||
".types[]{TypesItem",
|
||||
".sprites{Sprite",
|
||||
},
|
||||
maxLines: 250,
|
||||
},
|
||||
@ -32,9 +33,10 @@ func TestRawPathsFixtures(t *testing.T) {
|
||||
name: "swapi_person",
|
||||
file: "testdata/swapi-luke.json",
|
||||
mustContain: []string{
|
||||
".{Root0}.name{string}",
|
||||
".{Root0}.height{string}",
|
||||
".{Root0}.films[]{string}",
|
||||
"{Root0}",
|
||||
".name{string}",
|
||||
".height{string}",
|
||||
".films[]{string}",
|
||||
},
|
||||
maxLines: 30,
|
||||
},
|
||||
@ -42,8 +44,9 @@ func TestRawPathsFixtures(t *testing.T) {
|
||||
name: "swapi_planets",
|
||||
file: "testdata/swapi-planets.json",
|
||||
mustContain: []string{
|
||||
".{Root0}.count{int}",
|
||||
".{Root0}.results[]{ResultsItem",
|
||||
"{Root0}",
|
||||
".count{int}",
|
||||
".results[]{ResultsItem",
|
||||
"climate{string}",
|
||||
"population{string}",
|
||||
},
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user