I have a nested JSON HTTP response I want to map to my structs. All responses are formatted: {"_embedded": {"entity": [entity-specific json]}}. I want to pattern match on the entity to map the entity data to the correct struct.
Right now I’m doing something like this to pattern match on the decoded response:
def map_response(%{"_embedded" => %{"customers" => customers}}) do
customers |> Poison.encode! |> Poison.decode!(as: %Customer{addresses: [%Address{}]})
end
This works great, but I don’t like that I’m having to re-encode the HTTP response into order to utilize the decode!/2 function. I don’t know how to pattern match on the first part of the HTTP response without first decoding the response.
…so, as long as the situation is reasonably simple, the cost of doing all that dynamic work is somewhat steep, at least if you have to process a lot of requests
Thanks for the suggestions. This is just some sample data - the real data has too many fields to pattern match all the variables and set them in the struct.
I’ve taken a look at ExConstructor before, perhaps it’s time for another look.
I haven’t looked at Poison.decode/2 source code for this. But if the decoding process is not part of mapping the data to a specified struct, then abstracting that mapping function into a standalone one would be awesome.
You can put complex maps into structs by using the Poison.Decode.decode/2 function. You can create the map from an encoded JSON by using Poison.Parser.parse/1. Poison.decode/2 combines these steps.
If you’re making HTTP calls using HTTPoison, you can put in this override function which will parse the response body into a map:
def process_response_body(body) do
Poison.Parser.parse!(body)
end
Then pattern match on the response body and map to a struct as follows:
def map_response_body(%{"_embedded" => %{"customers" => customers}}) do
Poison.Decode.decode(customers, as: %Customer{addresses: [%Address{}]})
end