1

I am not sure if this question has been asked before but I can't find related custom mapping. Usually it is a direct JSON to object 1:1 mapping.

So here is my sample example:

class Test():
    id: str
    name: str
    msg: str

data = [
    {
        "id": "12345",
        "client": "test",
        "msg": "random"
    }, {
        "id": "54321",
        "client": "test-2",
        "msg": "random-2"
    }
]

So on above I have a JSON, I wanted to directly convert it to object I have on the first class. Note the "client" from the JSON becomes name.

So the final output when I do load the object it would become.

data = [
    {
        "id": "12345",
        "name": "test",
        "msg": "random"
    }, {
        "id": "54321",
        "name": "test-2",
        "msg": "random-2"
    }
]
6
  • Your class doesn't do anything. Should it be a dataclass? And where do you think the mapping client -> name comes from? Commented Jun 3, 2021 at 17:59
  • 1
    sorry I am fairly new to python coming from java background. what I was trying to do was create an custom object and have json mapped to that custom class. Commented Jun 3, 2021 at 18:01
  • It's not clear what you actually tried to implement that. Python will deserialize the JSON to a list of dicts, if you want something else you have to customise the process or convert it afterwards. Commented Jun 3, 2021 at 18:03
  • Is your json correct? Test has a "name" property but the json in data has "client" istead of "name" Commented Jun 3, 2021 at 18:08
  • And note that if your class doesn't have any behaviour you don't need to do this at all - Python isn't Java, you can often just stick with a dictionary. Commented Jun 3, 2021 at 18:19

2 Answers 2

3
class Test():
    def __init__(self, id, client, msg):
        self.id = id
        self.name = client
        self.msg = msg

data = [
    {
        "id": "12345",
        "client": "test",
        "msg": "random"
    }, {
        "id": "54321",
        "client": "test-2",
        "msg": "random-2"
    }
]

# unpack values from dict and pass in as arguments for Test.__init__()
objects = [Test(**item) for item in data] 
Sign up to request clarification or add additional context in comments.

4 Comments

I don't think it makes sense to encode that mapping client parameter -> name attribute in the initialiser, what about when you create instances that aren't from that JSON? Typically you'd do this as a class method, e.g. Test.from_dict(item).
The questions says that it should map from THIS JSON format. For other formats, it would need a different class.
If it was only for that JSON why would it need to rename a property? And would you really write multiple implementations of the same class for different sources? That seems like a bit of a smell.
Here's a good example of a healthier pattern: stackoverflow.com/a/30114013/3001761
2

You can use Pydantic as well to define your class like showed bellow:

from pydantic import BaseModel

class User(BaseModel):
    id: str
    name: str
    msg: str

    def __init__(self, id: str, client: str, msg: str) -> None:
        super().__init__(id=id, name=client, msg=msg)

users = [
    {
        'id': '12345',
        'client': 'test',
        'msg': 'random',
    },
    {
        'id': '54321',
        'client': 'test-2',
        'msg': 'random-2',
    }
]

objects = [User(**user) for user in users]

print(objects)
# Output
[
   User(id='12345', name='test', msg='random'),
   User(id='54321', name='test-2', msg='random-2')
]

2 Comments

this would only be fine but the problem is that response is returning "client" and I want to mapped to "name"
My bad. Updated the code in order to read the correct json.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.