Skip to content

Instantly share code, notes, and snippets.

@atwong
Created May 31, 2025 09:57
Show Gist options
  • Save atwong/cfc099362c3c0b1026a8f23380621d4b to your computer and use it in GitHub Desktop.
Save atwong/cfc099362c3c0b1026a8f23380621d4b to your computer and use it in GitHub Desktop.
Example classes that can un-nest python POPOs
from __future__ import annotations
from collections import UserDict
from dataclasses import dataclass
from typing import Type, Any, Optional
import json
"""
Example how to simplify a heavily-nested POPO
using a set of declarative classes. This is motivated
by GraphQL responses which contain heavily-nested
objects
Each class defines a list of FieldSpec
FieldSpec
- path attribute specifies the location of the value using
dot notation for nested keys
- dest attribute provides an alternate key, otherwise the
path leaf is used
- klass attribute (optional) specifies another class to
further process an inner object
"""
@dataclass
class FieldSpec:
path: str
dest: Optional[str] = None
klass: Optional[Type[BaseGQLFlat]] = None
class BaseGQLFlat:
_bare = False
_dspec = []
def __new__(self, src):
data = None if self._bare else {}
for cspec in self._dspec:
_src = src
for seg in cspec.path.split("."):
if seg not in _src:
break
_src = _src[seg]
else:
if isinstance(_src, list) and cspec.klass:
val = [
cspec.klass(item) for item in _src
if cspec.klass(item)
]
else:
val = cspec.klass(_src) if cspec.klass else _src
if not self._bare:
if val is not None:
key = cspec.dest if cspec.dest else seg
data[key] = val
else:
data = val
return data
class Micro(BaseGQLFlat):
_bare = True
_dspec = [FieldSpec(path="b")]
class Nano(BaseGQLFlat):
_dspec = [
FieldSpec(path="fix.me", dest="apple"),
FieldSpec(path="atl", klass=Micro),
]
class Newbie(BaseGQLFlat):
_dspec = [
FieldSpec(path="inner.tube"),
FieldSpec(path="air.press.com", dest="apc"),
FieldSpec(path="inner.casp", dest="hun", klass=Nano),
FieldSpec(path="air.nothing.b"),
FieldSpec(path="air.aruba", klass=Nano),
]
if __name__ == "__main__":
gqlinput = {
"inner": {
"tube": 1234,
"ast": "abc",
"flex": ["a", "c", "e"],
"casp": {
"fix": {
"me": "is_hun",
"ignored": 231
},
"orange": "apple",
"atl": [
{"a": 1, "b": 1},
{"a": 1, "c": 2},
{"a": 1, "b": 3},
]
}
},
"air": {
"press": {
"com": {"a": "zzz", "b": "zyx"},
"bbbb": 322,
},
"nothing": {"z": 1, "u": 55, "b": 66},
"aruba": {
"fix": {
"x": "xxxx"
},
"atl": {"k": "jjj"}
},
}
}
goutput = Newbie(gqlinput)
print(goutput)
print(f"{json.dumps(goutput, indent=2)}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment