Search code examples
crystal-lang

JSON.mapping if "root" attribute has inherit keys


I get response in for example next form:

resp = "{
  \"response\":
    {\"some\":
      {\"next\":
        {\"user\":
          {\"name\":\"Oleg\"}
        }
      }
    }
}"

I use JSON.mapping for combine user from JSON

struct User
  JSON.mapping(
    f_name: {type: String, key: "name", root: "WHAT.ABOUT.ROOT"}
  )
end

how I can use root attribute in this case, when I have inherit keys?

user = User.from_json(resp)

I tried root: "response.some.next.user" but it doesn't work

Thanks!


Solution

  • I found solution:

    require "json"
    private struct Response
      JSON.mapping(
        result: {type: Result, key: "get_users_response"}
      )  
    end
    
    private struct Result
      JSON.mapping(
        client: {type: Client, key: "get_users_result"}
      )
    end
    
    struct Client
      JSON.mapping(
        user: {type: User, key: "user"}
      )  
    end
    
    struct User
      JSON.mapping(
        id: {type: String, key: "id"},
        f_name: {type: String, key: "first_name"},
        l_name: {type: String, key: "last_name"}
      )
    end
    
    resp  = "{\"get_users_response\":{\"get_users_result\":{\"status\":\"Success\",\"error_code\":\"200\",\"user\":{\"id\":\"10\",\"first_name\":\"Oleg\",\"last_name\":\"Sobchuk\"}}}}"
    
    response_container = Response.from_json(resp)
    puts response_container
    puts response_container.result.client.user
    

    it looks a little difficult, but it works https://play.crystal-lang.org/#/r/1k3a

    EDIT

    According to THIS BENCHMARK with schema JSON parsing works little faster and use a much less memory.