Is there a better way to parse this JSON payload?

I am receiving a JSON payload which looks like this:

{
  "entry": [{
    "changes": [{
      "field": "feed",
      "value": {
        "item": "status",
        "post_id": "44444444_444444444",
        "verb": "add",
        "published": 1,
        "created_time": 1535243088,
        "message": "Example post content.",
        "from": {
          "name": "Test Page",
          "id": "1067280970047460"
        }
      }
    }]
  }]
}

to parse out various fields, I have functions set up like this:

defp extract_verb(data) do
  data
  |> Map.get("entry")
  |> List.first
  |> Map.get("changes")
  |> List.first
  |> Map.get("value")
  |> Map.get("verb")
end

Is there a better way I could be handling this?

You have a few choices depending on how you want to handle error situations. As a minor note, what you posted isn’t valid JSON ( "changes" happens as a key value thing but it’s part of a list, same thing with field and value.), which makes this a little harder to suggest concrete solutions.

If you want to be very assertive you can pattern match:

defp extract_verb(%{"entry" => [%{"changes" => [%{"value" => %{"verb" => verb}} | _]} | _]}) do
  verb
end

Alternatively you could use Access to just basically return nil if things don’t match up:

get_in(data, ["entry", Access.at(0), "changes", Access.at(0), "value", "verb"])
2 Likes

Oh really? That’s the webhook payload that the Facebook Graph API sends to me, so I just assumed they’d send me valid JSON. :frowning:

I’ll try pattern-matching first - thanks. :slight_smile:

You can test it yourself, none of the Elixir parsers will parse it if you copy it out of your forum post, and if you paste it into an online JSON validator you’ll get errors too. I’m assuming it’s just a copy / paste issue when you created the forum post.

Oh - I left out some brackets when uploading the code. Updated the JSON payload to be valid now.