Building Custom jSon hashes

Hi,

I'm building a web service that will be accessed from a phone.

So what I'm seeing so far is that building json responses seems to be
quite limited (but I think I'm just missing something)

Lets say I have users, and they can have different amounts of types of
debt. In this case the debt is calculated based on a couple of
different things. So in order to calculate debt I need to do some
things.

I also might want to return a status message (success/failure) with
each json resonse

I know I can do something like:
render format.json { :json => {:success => true, :user =>
@user.as_json } }

I can also overwrite as_json in the user model to customize the
output. I want to have more options than that thouse, since overwrite
as_json is kind of global. I'm imagining having specialized functions
that will return json that has a very different structure than the
model itself.

render format.json { :json => {:success => true, :user =>
@user.json_for_dropdown } }
render format.json { :json => {:success => true, :user =>
@user.json_for_invoice } }

Is this possible? How do I write json_for_X to return json etc? Is
there a better way to do this? Are there templates that can be used
for json like rendering partials?

Thanks

Joe

pipplo wrote in post #950214:

Hi,

I'm building a web service that will be accessed from a phone.

So what I'm seeing so far is that building json responses seems to be
quite limited (but I think I'm just missing something)

Lets say I have users, and they can have different amounts of types of
debt. In this case the debt is calculated based on a couple of
different things. So in order to calculate debt I need to do some
things.

I also might want to return a status message (success/failure) with
each json resonse

I know I can do something like:
render format.json { :json => {:success => true, :user =>
@user.as_json } }

I can also overwrite as_json in the user model to customize the
output. I want to have more options than that thouse, since overwrite
as_json is kind of global.

Overriding (not "overwriting", which means something else) as_json in
each model is usually the granularity you want -- there's a canonical
JSON representation of a User, valid through the whole application.

I'm imagining having specialized functions
that will return json that has a very different structure than the
model itself.

render format.json { :json => {:success => true, :user =>
@user.json_for_dropdown } }
render format.json { :json => {:success => true, :user =>
@user.json_for_invoice } }

Is this possible? How do I write json_for_X to return json etc?

The exact same way you'd write as_json.

But do you really want to? If you want different JSON structures, is
your application really trying to tell you that it needs different
classes? (Only you can tell this for sure. Just trying to get you
asking the right questions.)

Is
there a better way to do this? Are there templates that can be used
for json like rendering partials?

Sure, you can use a template for rendering JSON just as you can for any
other format. Rails doesn't care -- it's all just text.

Thanks

Joe

Best,

Is this possible? How do I write json_for_X to return json etc? Is
there a better way to do this? Are there templates that can be used
for json like rendering partials?

as long as json_for_X returns something that can be serialized to json
(ie strings, numbers, arrays, hashes etc) then rails will take care of
the rest.

Fred

Overwriting..I'm not even sure why I wrote that..I know better than
that.

I guess in general what I am getting at is that I might want the json
to return mutliple objects for a reason or calculated values. I dont
have a real example yet. I'm trying to define the interface between a
phone app and web service I'm just trying to understand how this works
before I get too far in and find out I can't do what I wanted in
rails. Hopefully this gives a good idea of what I mean.

Say I want to return a list of a users friends, and the number of
times they've been poked. The num_poked isn't a direct field in the
user, it's a calculated field in the friend model

Friend Model:
...
def num_pokes
user_pokes.sum("WHERE userid = x") # this is psuedo code just off the
top of my head
end
...

Sometimes I want to return an array of user ids, and num_pokes. If I
override as_json for friends, I would add a check for
option :num_pokes I guess, and then I could call it like this?

render format.json { :json => {:success => true, :user =>
@user.friends.as_json(:include => [:num_pokes] } }

def as_json(options={})

if options[:num_pokes]
    {num_pokes => self.num_pokes}
end

end

So that makes some sense, but this seems like it would just get really
ugly as you start including and excepting more and more values..which
is why I wanted to create a function to do it. This function would
also handle returning the standard things like success, errors, etc.

render format.json { :json => return_json_for_friends_list() }

I think this function that I am imagining would belong in the
UserHelper and not in the model itself...