6

I am attempting to port the Golang tutorial geddit to Elixir. I have done so successfully with Dartlang, but Elixir's operations on maps & lists are confusing for me.

Using HTTPoison and JSEX, I have the following code:

defmodule Redditex do
  use HTTPoison.Base

  def process_url(url) do
    "http://www.reddit.com/r/#{url}.json"
  end

  def process_response_body(body) do
    json = JSEX.decode! body
    json = Enum.map json, fn ({k, v}) -> {String.to_atom(k), v } end
    json
  end
end

My difficulty is parsing the JSON body into an appropriate struct where the JSON contains nested data. Jazz has some allusion to mapping to a structure but not with nested data.

Is there an example or a common practice to decode JSON in Elixir similar to Go's usage:

type Response struct {
Data struct {
    Children []struct {
        Data Item
    }
  }
}

type Item struct {
   Title    string
   URL      string
   Comments int `json:"num_comments"`  #mapping to another field label
}
3
  • Maybe the best way is to decode the JSON and then, when you want to work with the children, struct(Item, item_map_from_json)? Commented Aug 5, 2014 at 18:07
  • Struggling with that approach myself now. Newbie issues. But, I was looking for a library or built in support for building a structure based on the expected JSON response. So kinda of what you are saying at the Item level, which I am confused on how to do, but at the body level with nested structures. Commented Aug 5, 2014 at 20:07
  • 2
    Well, my idea was that if you need only the children, you would do something like: response["children"] |> convert_items_to_struct(). However, if you need to preserve the whole structure, you can use update_in/2 to traverse to a known nested level and update it. For example update_in response["children"], &convert_items_to_struct/1. Commented Aug 6, 2014 at 8:22

1 Answer 1

5

Using the Poison JSON library I was able to get partly there for handling the nesting:

def handle_response(%{status_code: 200, body: body}) do
    json = Poison.decode!(body, as: %{"data" => %{"children" => [%{"data" => Redditex.Item}]}})
    items = Enum.map( json["data"]["children"], fn (x) -> x["data"] end )
end

Enumertion is necessary to remove the anonymous structs and the remapping of the field names has not shown as a native solution. A work path forward nonetheless.

Sign up to request clarification or add additional context in comments.

Comments

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.