How do I turn Moose objects into JSON for use in Catalyst?

泪湿孤枕 提交于 2019-12-22 14:59:32

问题


I have a series of Moose objects that I'm looking to feed to JSON::XS by way of Catalyst::View::JSON. JSON::XS is unable to encode blessed data-structures. I know that there is MooseX::Storage::Format::JSON which can -- kinda -- do what I want; but, it seems pretty overly heavy. What I'm looking for is essentially the same information that XXX.pm provides. I just want the raw-data structures recursively unblessed so JSON::XS (the driver for JSON::Any that C:V:JSON uses internally) can display it.

What is the best way go about using Catalyst::View::JSON and JSON::XS with Moose objects? It seems I have four obvious choices:

  1. Make Catalyst::View::JSON work with Moose Objects, by patching C:V:JSON to read from freeze and finalize the request if the argument exposed is a Moose Object.
  2. Patch JSON::XS to fallback to return value of $obj->freeze if $obj->isa('Moose') && $obj->does('MooseX::Storage::Format::JSON'). I should look into MX:S:F:JSON to make sure that the class used by JSON::Any, and by proxy MX:S:F:JSON, is JSON::XS (hate to think of the bugs galore if JSON::Any choses a different internal encoder for the Moose object that JSON::XS is called to use.
  3. Figure out how to recursively-unbless and let Catalyst::View::JSON do its thing.
  4. Don't use Catalyst::View::JSON at all. Just write to STDOUT $obj->freeze and manually finalize requests.. This seems the most hackish.

I'm sure there are some other options, any ideas? What is my best bet?


回答1:


I tend to do option 3 using MooseX::Storage to provide a pack() method that returns a Perl data structure that I can stuff in my stash so the View can render it as it chooses.

Also note that JSON::Any can be forced (by the environment, or by passing the proper parameters to import()) to pick a specific backend. This is how the test suite works, and it is documented.




回答2:


If you don't care about unblessing your object completely and making it completely unusable (from a Moose perspective), try unbless from Data::Structure::Util.

I personally prefer MooseX::Storage for a much more elegant and sustainable solution.




回答3:


Like it or hate it my ultimate solution was to revert back to the now deprecated JSON::Syck which does exactly what I want. Here is a quick non-Moose example of logical non-Moose serialization to JSON.

use JSON::Syck;
use URI;
use feature ':5.10';
say JSON::Syck::Dump(
 bless { foo => URI->new("http://www.evancarroll.com") }
)

I wrote the author about JSON::XS he was not game for adding the functionality. Here is some of the text (taken out of context from numerous messages to show why this feature isn't there) from Marc Lehmann the JSON::XS maintainer:

No, because you are using JSON and not Perl. Perl is obviously capable of representing any Perl data structure, but JSON is not, so you need to tell it what to do. Many people naively request something like "just dump the data structure", but JSON can't even represent all perl data structures that are non-objects.

...

Your question is like: why can't I send this 1MB jpeg image as ascii file - simply because ascii cannot represent octets.

...

Or maybe you justw ant to to throw some garbage at it and expect JSON::XS to do what is good for you (but wrong for other people) - there is simply no way for JSON::XS to magically guess what you want.

...

TO_JSON is it. Anything else is just wild guessing.

...

Then maybe you should try stuff that JSON can actually represent. Throwing some object hierarchy at it and hoping it would do "the right thing" is clearly bad software engineering - try not to resort hacks, when your protocl requires JSON, then send JSON, don't expect the json library to fix up your invalid message in the first place.

I don't know how to respond to that, other than I DON'T CARE. JUST WORK! LIKE ::SYCK. I don't expect objects to transform to JSON perfectly. But, I think I fall in the 80% that just want it to work. I'm using JSON for jQuery import not performing banking transactions during brain surgery. Ultimately, I don't want to use a special role... I want anything sent to it to magically be transformed for me to a level that makes it useful in a response to a jQuery JSON request.

UPDATE

Sorry, I missed these replies until someone said I was trolling in an unrelated medium. MooseX::Storage doesn't work for non-Moose classes, I want a general way to represent the stash in a JSON format. Unfortunately, some of those members of the stash are Moose objects. XML::Simple can do this, Data::Dumper can do this, JSON::Syck can do this, the list goes on -- I just want it done. It doesn't have to be 1:1 with Perl, and to be honest I want it done fairly close to the way JSON::Syck does it by default. My argument here then, is, "How do I get JSON::XS to work exactly like JSON::Syck does currently"? And, your answer is you can't. So I've not employed a different solution. Writing code costs money, why would I want to write to_JSON if Syck is already doing it right... I'd like to say the burden is on the nay-sayers to show what Syck is serializing a fashion that isn't desirable. Also, do keep in mind JSON::Syck was seeded by Audry, who is by no means a troll, idiot, or "brain damaged"; or, any of the other terms that are being thrown my way. I will close with this: the lack of a bad serialization route of JSON::Syck and the desired output already just-working leads me to believe this is a good choice for me. And, what could MooseX::*:JSON be doing differently with an arbitrary Moose object? Why do you think that code can't be written to accept a Moose object rather than a method on it? If you think otherwise, answer with something of substance -- I'd like to see a better response. Thanks. (directed toward @jrockway, and @Ether)



来源:https://stackoverflow.com/questions/3391967/how-do-i-turn-moose-objects-into-json-for-use-in-catalyst

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!