I'm migrating a Grails 2.2.5 app to Grails 4.0.2, and I have it working OK but now want to start taking advantage of new features that came in with Grails 3 and 4, such as improvements in the area of JSON responses. I've been having a play with JSON Views and the use of respond, and have some test methods working. Still struggling in some areas, though. For example, I have in multiple places in controllers code which produces a Map, which I then return via render map as JSON. This works fine, with the JSON representation of the objects in the map being determined by customer marshallers using JSON.registerObjectMarshaller(MyClass).
My understanding is that the use of respond and JSON Views for such things is now being encouraged, in preference to the render xxx as JSON approach (please correct me if I'm wrong). So two questions arise from this:
For my 'weekSummary' method in my SaleController, for this to work I presumably need to create a 'weekSummary.gson' file in /sale/views. What should that gson file look like? I've tried with e.g.
model {
Map map
}
json map
but this just renders null. How do I handle maps in JSON views?
What advantages does this give me over render xxx as JSON, given that it is a little more cumbersome (having to create a new GSON file)?
Related
Because I am rewriting a legacy app, I cannot change what the clients either send or accept. I have to accept and return JSON, HTML, and an in-house XML-like serialization.
They do, fortunately set headers that describe what they are sending and what they accept.
So right now, what I do is have a decoder module and an encoder module with methods that are basically if/elif/else chains. When a route is ready to process/return something, I call the decoder/encoder module with the python object and the header field, which returns the formatted object as a string and the route processes the result or returns Response().
I am wondering if there is a more Quart native way of doing this.
I'm also trying to figure out how to make this work with Quart-Schema. I see from the docs that one can do app.json_encoder = <class> and I suppose I could sub in a different processor there, but it seems application global, there's no way to set it based on what the client sends. Optimally, it would be great if I could just pass the results of a dynamically chosen parser to Quart-Schema and let it do it's thing on python objects.
Thoughts and suggestions welcome. Thanks!
You can write your own decorator like the quart-schema #validation_headers(). Inside the decorator, check the header for the Content-Type, parse it, and pass the parsed object to the func(...).
I have implemented a Json-ld dynamic creation process to boost my SEO. The JSON is created through the use of Jbuilder ( code is in a partial), rendered in a script tag with a type of "application/ld+json". All of it is wrapped up in a content_for, so that I can reuse the logic.
Once it has been implemented, I started to get this error in my console: "[Facebook Pixel] - Unable to parse JSON-LD tag. Malformed JSON found: ' "
I tested my Json-LD on the google structured data tool and everything came back ok.
I've added an hand written JSON-LD in my script tag, instead of my aforementioned logic,
everything looked ok. No error was displayed in the console, and Chrome Facebook Pixel
Helper was able to find my JSON-LD.
Bottom line, it appears that using my dynamic logic with the partials create a random " ' ", which makes no sense for me.
Any of you ever had the same issue, or something similar ?
May be templating engine is messing you up. You might consider using the json-ld gem to validate the output as part of continuous integration (you can also semantically validate the content using other gems).
I’ve had success using JSON-LD in Haml, but I just use to_json from a Hash hierarchy which has always worked well for me.
Ive been searching through source for a while, and it appears to me that there are no given Rails tools for retrieving the String representation of various HTML content types. Ive also found this to be a very difficult concept to search for in general.
What I want is something like this:
Mime::Mimes::CONTENT_TYPE_JSON = 'application/json'.freeze
or, Mime::Mimes::CONTENT_TYPES[:json] etc.
...because I want to do a lot of things like some_value == 'application/json' or some_value = 'application/json' etc.
I want to use the expression "application/json" often, and I dont want to create new String instances for something that is pretty well within the domain of web application development. Ive thought of creating my own app consts or vars so I dont have to allocate HTML Content Type strings more than once, but also feel this should just be available for me in any web application framework (at least, those written in languages where every string is a new memory allocation).
Is there a better tool or resource within the Rails 5 source that I am missing that allows easy retrieval of content type strings? Do I have to get a gem / create my own for this?
Note: Im away of how heavy of an "optimization" this may appear to be. Let's then entertain this query from a position of being pragmatic about organizational style, for a project that requires elimination of any duplication of domain-specific string literals, and to keep them symbolized or as some frozen const. Let's pretend its a personal project for the sheer joy of experimenting with such style!
There is a shorthand for it:
Mime[:json]
Mime#[] -
https://github.com/rails/rails/blob/e2efc667dea886e71c33e3837048e34b7a1fe470/actionpack/lib/action_dispatch/http/mime_type.rb#L41
which uses
Mime::Type#lookup_by_extension -
https://github.com/rails/rails/blob/e2efc667dea886e71c33e3837048e34b7a1fe470/actionpack/lib/action_dispatch/http/mime_type.rb#L149
If you want to get the actual content type you might need to call a #to_s on it:
Mime[:json].to_s
Creating a new module to facilitate simple storage and retrieval using the ActionPack Mime::Type system would work as follows:
# Build hash of type name to value, e.g., { xml: "application/xml" }
CONTENT_TYPES = {}.tap do |simple_content_types_hash|
# Get each registered Mime Type
Mime::EXTENSION_LOOKUP.each do |mime|
simple_content_type_hash[mime.first.to_sym] = mime.last.instance_variable_get("#string").freeze
end
end.freeze
Note: the above is untested, its just a generalization of what I am looking for. Thanks to #Fire-Dragon-DoL for the tip.
This could be added via an initializer, patched into an existing module, or into a new helper module.
Is there a way to generate XML from the configuration/programming used by the Rails AciveModelSerializer gem? AMS seems to only generate customized JSON. XML comes out in a default format.
I've seen references to AciveModelSerialization and that it supports JSON and XML, but the configuration, while similar, is different. What is the story with the difference between them? Is one going away? How do they compare in real use (other than format capability)?
As you can see here, there (and at other spots), XML is slowly disappearing from the web. There are a couple of reasons for that. 1 - JSON objects are smaller. 2 - JSON is the de-facto format for most client-side javascript libraries. 3 - Fashion, people like it.
You can still use ActiveModel to serialize Xml if you wish so:
http://api.rubyonrails.org/classes/ActiveModel/Serializers/Xml.html
Hope it helps.
I have a web scraper built to parse html from a website and I'm trying to write tests for it.
The class I'm trying to test receives a Nokogiri HTML object and extracts the required data from it. Now as usual the html can vary, sometimes elements will be missing or whatnot. I need to test these different situations.
So what I'd like to do is make a bunch of html files, each one representing a case with a particular element missing etc. For each html file, I wish to also construct an associated hash of the data I would expect the scraper to extract, assuming it is working correctly.
So I would like to write a test which will iterate over these html files and compare the data extracted by the class being tested against the expected data and report whether or not it is correct.
Any suggestions as to how to do this?
Have a look at the Artifice, fakeweb or webmock gems, which override net/http in order to supply testable results.