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:
- Make
Catalyst::View::JSON
work with Moose Objects, by patchingC:V:JSON
to read fromfreeze
and finalize the request if the argument exposed is a Moose Object. - Patch
JSON::XS
to fallback to return value of$obj->freeze if $obj->isa('Moose') && $obj->does('MooseX::Storage::Format::JSON')
. I should look intoMX:S:F:JSON
to make sure that the class used byJSON::Any
, and by proxyMX:S:F:JSON
, isJSON::XS
(hate to think of the bugs galore ifJSON::Any
choses a different internal encoder for the Moose object thatJSON::XS
is called to use. - Figure out how to recursively-unbless and let
Catalyst::View::JSON
do its thing. - 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?
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.
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.
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