Clojure name binding to REST JSON data - json

I'm a Frontend Engineer, our team is switching many of our old services to micro services written in clojure. The main issue I'm seeing is that clojure naming conventions prefer hyphens to-separate-words in variable names. This means if you straight map variables into JSON any JS consumer would need to access this data using bracket notation e.g. response['to-separate-words']. This is obviously not ideal. I thought this would be a easy best practice to lookup but I've been looking for an hour and it seems like all the docs I read avoid this issue but using single words. Has anyone else dealt with this.

You might use camel-snake-kebab library which supports most of the combinations. You can plug it in into most of the JSON libraries for Clojure (cheshire, cli-json, data.json - as mentioned by Elogent) as they usually have an option to provide a function for handling property name mangling.
For example with cheshire:
Generate JSON with camel case property names:
(cheshire.core/generate-string {:my-clojure-key "abc"}
{:key-fn camel-snake-kebab.core/->camelCaseString})
Result:
{"myClojureKey":"abc"}
Parse JSON to get map with kebab case keys:
(cheshire.core/parse-string "{\"myClojureKey\":\"abc\"}"
camel-snake-kebab.core/->kebab-case-keyword)
Result:
{:my-clojure-key "abc"}
There is also an example for data.json in camel-snake-kebab readme.

Related

Debugging json4s read deserialization errors

I am attempting to consume an API that I do not have control over which is somewhat poorly documentented and somewhat inconsistent. This means that sometimes, the API returns a different type than what is documented or what you would normally see. For this example, we'll look at a case when an array was returned in a place where I would normally see a string. That makes a crappy API, but my real problem is: How can I more easily track those things down? Right now, the errors look something like this:
No usable value for identifier
Do not know how to convert JArray(List(JString(3c8723eceb1a), JString(cba8849e7a2f))) into class java.lang.String
After deciphering the problem (why JValue::toString doesn't emit a JSON string is utterly perplexing to me), I can figure out the API returned an array when I made my case class only able to deal with Strings. Great. My issue is that finding this discrepancy between my object model and the contents of the JSON seems significantly more difficult than it should be.
Currently, this is my workflow for hunting down decoding errors:
Hope bad data has some sort of identifying marker. If this is not true, then it is way more guesswork and you will have to repeat the following steps for each entry that looks like the bad bits.
Go through the troubles of converting the JArray(List(JString(...), ...)) from the error message into valid JSON, hoping that I encode JSON the same way at the API endpoint I got the data from does. If this is not true, then I use a JSON formatter (jq) to format all data consistently.
Locate the place in the source data where the decoding error originates from.
Backtrack through arrays and objects to discover how I need to change my object model to more accurately represent what data is coming back to me from the API.
Some background: I'm coming from C++, where I rolled my own JSON deserialization framework for this purpose. The equivalent error when using the library I built is:
Error decoding value at result.taskInstances[914].subtasks[5].identifier: expected std::string but found array value (["3c8723eceb1a","cba8849e7a2f"]) at 1:4084564
This is my process when using my hand-rolled library:
Look at the expected type (std::string) compared with the data that was actually found (["3c8723eceb1a","cba8849e7a2f"]) and alter my data model for the path for the data in the source (result.taskInstances[914].subtasks[5].identifier)
As you can see, I get to jump immediately to the problem that I actually have.
My question is: Is there a way to more quickly debug inconsistencies between my data model and the results I'm getting back from the API?
I'm using json4s-native_2.10 version 3.2.8.
A simplified example:
{ "property": ["3c8723eceb1a", "cba8849e7a2f"] }
Does not mesh with Scala class:
case class Thing(property: String)
The best solution would be to use Try http://www.scala-lang.org/api/current/#scala.util.Try in Scala, but unfortunately json4s API cannot.
So, I think you should use Scala Option type http://www.scala-lang.org/api/current/#scala.Option .
In Scala, and more generally in functional languages, Options are used to represent an object that can be there or not (like à nil value).
For handle parsing failures, you can use parse(str).toOption, which is a function that return an Option[JValue], and you can doing a pattern matching on the resulting value.
For handling extraction of data extraction into case classes, you can use extractOpt function, to do pattern matching on the value.
You can read this answer : https://stackoverflow.com/a/15944506/2330361

Configure Play/Jerkson to deserialize single quoted (non-standard) JSON w/o duplicating a lot of code

In a Play 2.0 application, I need to deserialize some JSON from a source which I don't control which uses single-quotes around strings -- where the JSON spec calls for double-quotes.
The solution using Jackson is here:
Configure Jackson to deserialize single quoted (invalid) JSON
But trying to implement this solution in play2.0 I hit a wall of static objects and private classes... it should be enough to replace object JerksonJson with one implementing the solution linked above at initialization, but because it is a static object it can't be extended, and id I try to copy it into my code I need to drag along classes PlaySerializers, PlayDeserializers, JsValueDeserializer,... I stopped here, as it looked like too much.
Is there a clean solution?
How about trying to fix the invalid json string by replacing every ' in it with a "?
That would work if 's are only used for specifying strings.
I realize that this may not help too much with Play framework part, but perhaps you could use Jackson Scala Module instead of Jerkson? Doing that should make it easier to just use ObjectMapper, with Scala module registered, instead of having to use Jerkson-specific handlers.

Single serialization layer to Json with Casbah/Salat

I am trying to create a serialization layer which allows me to:
Store my classes in a MongoDB data source
Convert them to JSON to use them in a REST API.
Some classes are clearly not case classes (because they are inherited from a Java codebase) and I would have to write ad-hoc code for that. Is registering a BSON Hook for my non standard type the correct approach, and does it provide Json serialization?
Salat maintainer here.
You might prefer to create a Salat custom transformer instead of registering a BSON hook with Casbah.
See simple example and spec.
If you run into any issues, feel free to ping the mailing list with a small sample Github project that demonstrates what isn't working.

How to encode JSON in ABAP before 7.02

As Horst Keller mentioned in his ABAP and JSON post, "with Releases 7.02 and 7.03/7.31 (Kernelpatch 116) JSON is supported natively in ABAP".
Appartently 7.02 in my case of too generic because the line below:
writer = cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ).
returns the error: "The field CO_XT_JSON is unknown, but there is a field with the similar name CO_XT_XOP".
So is there any way to easily generate JSON?
Edit: Screenshot from SAP - Status
About the class CL_TREX_JSON_SERIALIZER: I also used this class during developping a mobile sap application and I found the created JSON not being valid, thus I started googling and found this http://scn.sap.com/community/mobile/blog/2012/09/24/serialize-abap-data-into-json-format (which also explains how to create a valid JSON serializer).
Validate your json with json lint http://jsonlint.com/ to see if it is valid.. otherwise, thats for sure, you get a lot of trouble in debugging why it doenst work and dont get the point that the serializer is corrupt. regards, zY
take a look at the ZCL_MDP_JSON Library. You can parse/encode any JSON. So, it is best suited for JSON scenarios that requires flexibility.
It is easy to understand if you have used JSON in other languages. You only need to study methods of ZCL_MDP_JSON_NODE class once & look at the examples.
Here is an extended overview of the library:
http://scn.sap.com/community/abap/blog/2016/07/03/an-open-source-abap-json-library--zclmdpjson
GitHub repo with examples directory: https://github.com/fatihpense/zcl_mdp_json
Disclaimer: I'm the author of the project. If you have questions, don't hesitate to contact me.
Here is some code I wrote for ABAP data <-> JSON conversion some time ago before the new capabilities were included with ABAP (or maybe it was just an older system).
https://gist.github.com/mydoghasworms/2291540
Include the code in your ABAP source and use the method data_to_json of the class.
A nice overview of custom ABAP <-> JSON serializers including yet another one can be found in this blog post
Most popular from my point of view is SE38's ZJSON-library which can be installed using SAPLINK (and which - in contrast to many others) has an explicit license attached to it: Apache 2.0
If upgrading to a newer patch isn't an option in the short term, you can also use class CL_TREX_JSON_SERIALIZER to serialise objects to JSON. A little bit of a quick-and-dirty solution but it works well.

HTML::Template Perl

IIs there a package similar to HTml::Template in perl which takes a JSON object and maps it to a HTML template file? I am building a web application using HTML::Template and will be receiving JSOn from a web services API, things will be made simple if I can templatize this JSOn to HTML instead of doing it the exact way HTML::Template requires.
HTML::Template just takes a data structure consisting of strings, hashes and arrays. JSON maps directly onto that.
$template->param(myData => JSON::Any->new->decode($json_string));
HTML::Template is a rather 'simple' templating engine - I am using quotes because its simplicity let's you do whatever you need in a view part from the Model View Controller architecture.
However, you can not execute arbitrary perl code inside a HTML::Template.
Also, due to the fact that in JSON you could have very complex data structures, I doubt that there are any suitable ways of using JSON in a straight way in your templates.
The only solution I see as possible is for you to use a Perl script that will parse the JSON, create some 'objects' and pass them to your templates. You already have that perl script - is the one that instantiate your HTML::Template object.
ok, a bit late, but:
HTML::Template always wants a hash of arrays of hashes and so on.
and you cannot navigate through the parameter stash.
If you want to do this, you might try out HTML::Template::Compiled which allows you to do this.
<tmpl_var some_hash.key.another_key[23] >
or with alternative delimiters:
[%= some_hash.key.another_key[23] %]
but note the documented differences of the module to HTML::Template.
So you decode your JSON string to a data structure and pass it to the template and then you can access all values somewhere deep in the structure.