jcrist / msgspec

A fast serialization and validation library, with builtin support for JSON, MessagePack, YAML, and TOML
https://jcristharif.com/msgspec/
BSD 3-Clause "New" or "Revised" License
2.01k stars 59 forks source link

Hot to get field alias name from Struct? #672

Closed Olegt0rr closed 2 months ago

Olegt0rr commented 2 months ago

Question

  1. Create struct
    
    from msgspec import Struct, field

class HelpIssue(Struct, kw_only=True): user_id: int | None = field(default=None, name="userId")


2. Then I need to get `name` from field `user_id`

```python
struct_field_name = "user_id"
struct_field = getattr(HelpIssue, struct_field_name)

print(struct_field.name) 
# Expected: "userId"
# Received: AttributeError: 'member_descriptor' object has no attribute 'name'
uwinx commented 2 months ago

@Olegt0rr, I think inspect.type_info will do the right job for you.

from msgspec.inspect import type_info

# to access "user_id" field's metadata
field_meta = type_info(HelpIssue).fields[0]
assert field_meta.name == "user_id"
assert field_meta.encode_name == "userId"

References: https://jcristharif.com/msgspec/inspect.html

Olegt0rr commented 2 months ago

@uwinx, thanks!

I've also found this way:

for name, encode_name in zip(
    struct.__struct_fields__,
    struct.__struct_encode_fields__, 
):
    ...
jcrist commented 2 months ago

msgspec.inspect.type_info is one way, but it's a bit overkill for this use case. And __struct_encode_fields__ is technically non-public (and may be removed in the future). The best way to get this information is to use msgspec.struct.fields (docs). You're looking for the encode_name attribute on FieldInfo in the result:

In [3]: class Example(msgspec.Struct):
   ...:     user_id: int = msgspec.field(name="userId")
   ...: 

In [4]: msgspec.structs.fields(Example)
Out[4]: (FieldInfo(name='user_id', encode_name='userId', type=<class 'int'>, default=NODEFAULT, default_factory=NODEFAULT),)