In my grails application I want to render hierarchy of objects as JSON response. There are several properties of java.util.Date type, specified on different levels, having different names. Depending on the location and name, I want to render date differently, something like this:
{
...
"touristBirthday": "1980-10-11",
"flight": {
...
"flightTime": "2013-10-11 10:00",
...
}
...
}
Note that touristBirthday and flightTime have both java.util.Date type, but should be rendered differently. So grails object marshaller is not really useful for me.
In some parts of the application I've already done conversion manually by transforming my model beans into maps and then overriding entries in these maps, but doing this in each case produces lots of unmaintainable mess, especially when the hierarchy has many levels.
Is there any plugin or simple solution to this problem? So I can simply specify name/location of my property and the way to render it, overriding default object marshaller.
P.S. changing the model (property types) is not really an option for me, as the model comes from another application.
Related
To keep this simple:
I have classes defined in typescript which have methods and properties (with lots of getter/setter logic). I then retrieve json data matching such classes. I need to be able to project these json objects into my "smart" classes. I know about class transformer but I wonder if this is really go-to approach to do this kind of stuff. Furthermore, I'm planning on using ngrx, so this whole class-transformation just looks wrong (server to json, json to state, state to class? and viceversa? I just dont see a clear pattern.
Any clarity is appreciated. Thanks!
I'm doing almost exactly what you describe in a fairly large app.
I'm using class-transformer to transform the JSON from http calls to instances of the appropriate objects, and then using the resulting objects as state in a store (except that I'm using Redux instead of ngrx).
I find that it works very well.
I'm not sure exactly what you mean by "server to json, json to state, state to class? and viceversa?".
For me (using your terminology), it's server to json, json to class, class to state
(but state is just a collection of objects, i.e. class instances. I.E. state is objects).
If I need to send state back to the server, then yes, I typically pull the appropriate objects from the store, serialize them to JSON, and send them to the server. But...the Angular HttpClient does the serialization for you, so you don't typically have to write that part, unless you need some custom serialization.
I have some sensitive domain objects that I would like to convert to json and xml. I am using spring view resolution to do this, but that is beside the point.
I'd like to add annotations to the domain objects to specify which fields should be converted to xml / json.
Something like
#XmlRootElement
public class SensitiveDomainObject {
...
public String getPassword() {...}
#XmlAttribute
#JsonValue
public String getAccountName() {...}
#XmlAttribute
#JsonValue
public String getGoldMemberStatus() {...}
}
I want getAccountName() and getGoldMemberStatus() to be serialised to json and xml, but getPassword to never be serialised.
What I don't want is
1) Separate 'annotation placement strategies' for json and xml as that gets confusing if one needs to markup different methods in different ways as standard.
2) To be explicitly ignoring fields. This is because if some programmer comes along in the future and adds a newly sensitive field without including for example the #JsonIgnore annotation, suddenly that sensitive field is shared.
3) To have to make methods like getPassword() private. I still want to be able to call getPassword() internally.
Has anyone done this or have any thoughts?
EDIT
Included a picture from IBM showing essentially the design I ran with, with explicit DTOs with annotations in the business logic layer. The presentation layer figures out which DTO to request and serve based on the incoming URL.
If you care so much about differentiating what you your business classes are and what is transferred, you may consider implementing a separate package of DTO classes which will explicitly include only those properties you'd like to transfer.
In this case you'll have to explicitly include the transfer properties, this can't happen because the programmer forgot it.
There are other approaches to this like adding some validation rules that the property like password is ignored and enforce them on JAXB context level. But this will only work until someone not knowing will name it kennwort or credentials or whatever may come in mind and your validation rules will be out of effect.
So I see two way:
* Either you trust the programmer (and all the QA/QS process like code reviews etc.) to support her/him.
* Or you make your transfer classes explicit.
For important external interfaces I'd probably go with the second approach (explicit DTOs). If password ends up there, it can't be by forgetting, it will only be on purpose.
We're in a process of switching from Json.NET to ServiceStack.Text and I came across an issue with serialization of polymorphic collections.
In JSON.NET I used to create a custom JsonCreationConverter and overriding the Create() method to select the type I want to create - as outlined here:
http://dotnetbyexample.blogspot.co.uk/2012/02/json-deserialization-with-jsonnet-class.html
The collection in question is List<ItemBase> which can contain FlightItem or CarHireItem objects.
This is my version of the Create() method for JSON.NET:
protected override ItemBase Create(Type objectType, JObject jsonObject)
{
var itemType = jsonObject["Type"].ToString();
switch (itemType)
{
case "flight":
return new FlightItem();
case "carhire":
return new CarHireItem();
default:
return null;
}
}
Is that possible with ServiceStack?
Serialization and deserialization in ServiceStack for polymorphic collections works, however, it appends the object type to the JSON output, e.g.
"__type" : "TestProject.Model.FlightItem, TestProject"
This means that I need to supply the type when posting JSON and I'm not too keen on having the .NET type visible for anyone within the API calls.
Any suggestions? If it's possible to do this in a different way, can you point me to some examples?
Firstly, Interfaces or abstract types in DTOs are a bad idea.
You're now in the strange position where you're trying to support polymorphic types in DTOs, but don't want to provide JSON Serializer-specific info? The reason why you need bespoke code to support polymorphic DTO's is because it's impossible to tell what concrete type should be used based on the wire format, hence why ServiceStack emits the __type property for this purpose.
To avoid these hacks, and have it work equally well in all JSON Serializers, you're better off "flattening" your polymorphic types into a single "flat" DTO and send that across the wire instead. Once you're back in C# you can use code to project it into the ideal types.
ServiceStack does provide some JsConfig<ItemBase>.RawDeserializeFn that will let you do something similar, see the CustomSerializerTests for an example. There's also the JsConfig<ItemBase>.OnDeserializedFn hook that can potentially help, but it's dependent on whether ItemBase contains a complete property list of both concrete types.
I'm developing a RESTful interface which is used to provide JSON data for a JavaScript application.
On the server side I use Grails 1.3.7 and use GORM Domain Objects for persistence. I implemented a custom JSON Marshaller to support marshalling the nested domain objects
Here are sample domain objects:
class SampleDomain {
static mapping = { nest2 cascade: 'all' }
String someString
SampleDomainNested nest2
}
and
class SampleDomainNested {
String someField
}
The SampleDomain resource is published under the URL /rs/sample/ so /rs/sample/1 points to the SampleDomain object with ID 1
When I render the resource using my custom json marshaller (GET on /rs/sample/1), I get the following data:
{
"someString" : "somevalue1",
"nest2" : {
"someField" : "someothervalue"
}
}
which is exactly what I want.
Now comes the problem: I try to send the same data to the resource /rs/sample/1 via PUT.
To bind the json data to the Domain Object, the controller handling the request calls def domain = SampleDomain.get(id) and domain.properties = data where data is the unmarshalled object.
The binding for the "someString" field is working just fine, but the nested object is not populated using the nested data so I get an error that the property "nest2" is null, which is not allowed.
I already tried implementing a custom PropertyEditorSupport as well as a StructuredPropertyEditor and register the editor for the class.
Strangely, the editor only gets called when I supply non-nested values. So when I send the following to the server via PUT (which doesn't make any sense ;) )
{
"someString" : "somevalue1",
"nest2" : "test"
}
at least the property editor gets called.
I looked at the code of the GrailsDataBinder. I found out that setting properties of an association seems to work by specifying the path of the association instead of providing a map, so the following works as well:
{
"someString" : "somevalue1",
"nest2.somefield" : "someothervalue"
}
but this doesn't help me since I don't want to implement a custom JavaScript to JSON object serializer.
Is it possible to use Grails data binding using nested maps? Or do I really heave to implement that by hand for each domain class?
Thanks a lot,
Martin
Since this question got upvoted several times I would like to share what I did in the end:
Since I had some more requirements to be implemented like security etc. I implemented a service layer which hides the domain objects from the controllers. I introduced a "dynamic DTO layer" which translates Domain Objects to Groovy Maps which can be serialized easily using the standard serializers and which implements the updates manually. All the semi-automatic/meta-programming/command pattern/... based solutions I tried to implement failed at some point, mostly resulting in strange GORM errors or a lot of configuration code (and a lot of frustration). The update and serialization methods for the DTOs are fairly straightforward and could be implemented very quickly. It does not introduce a lot of duplicate code as well since you have to specify how your domain objects are serialized anyway if you don't want to publish your internal domain object structure. Maybe it's not the most elegant solution but it was the only solution which really worked for me. It also allows me to implement batch updates since the update logic is not connected to the http requests any more.
However I must say that I don't think that grails is the appropriate tech stack best suited for this kind of application, since it makes your application very heavy-weight and inflexbile. My experience is that once you start doing things which are not supported by the framework by default, it starts getting messy. Furthermore, I don't like the fact that the "repository" layer in grails essentially only exists as a part of the domain objects which introduced a lot of problems and resulted in several "proxy services" emulating a repository layer. If you start building an application using a json rest interface, I would suggest to either go for a very light-weight technology like node.js or, if you want to/have to stick to a java based stack, use standard spring framework + spring mvc + spring data with a nice and clean dto layer (this is what I've migrated to and it works like a charm). You don't have to write a lot of boilerplate code and you are completely in control of what's actually happening. Furthermore you get strong typing which increases developer productivity as well as maintainability and which legitimates the additional LOCs. And of course strong typing means strong tooling!
I started writing a blog entry describing the architecture I came up with (with a sample project of course), however I don't have a lot of time right now to finish it. When it's done I'm going to link to it here for reference.
Hope this can serve as inspiration for people experiencing similar problems.
Cheers!
It requires you to provide teh class name:
{ class:"SampleDomain", someString: "abc",
nest2: { class: "SampleDomainNested", someField:"def" }
}
I know, it requires different input that the output it produces.
As I mentioned in the comment earlier, you might be better off using the gson library.
Not sure why you wrote your own json marshaller, with xstream around.
See http://x-stream.github.io/json-tutorial.html
We have been very happy with xstream for our back end (grails based) services and this way you can render marshall in xml or json, or override the default marshalling for a specific object if you like.
Jettison seems to produce a more compact less human readable JSON and you can run into some library collision stuff, but the default internal json stream renderer is decent.
If you are going to publish the service to the public, you will want to take the time to return appropriate HTTP protocol responses for errors etc... ($.02)
from Jersey a classic JSON output of List looks like:
{"SubtaskType":{"id":"4","name":"mozaika","metric":"m2","code":"104"}}
But GSON will say it's not a JSON array and experimentally, it accepts:
{"id":"4","name":"mozaika","metric":"m2","code":"104"} for single SubtaskType.
I tested it with JSON validator and it seems that both forms are acceptable.
GSON's output of List looks like:
[{"name":"aa","metric":"m2","id":1,"code":200},{"name":"bb","metric":"m","id":2,"code":300}]
Is there a way to configure GSON to parse/generate the longer form (with type name)?
Edit:
This is the structure (added for change/discussion):
public class SubtaskType {
private int id;
private String name;
private String metric;
private int code;
//getters & setters
}
Note: This answer is based on the original version of the question.
from Jersey a classic JSON output of List looks like:
{"SubtaskType":{"id":"4","name":"mozaika","metric":"m2","code":"104"}}
Really? That's not a JSON array, i.e., list. It's an object with one element named "SubtaskType", for which the element's value is an object with four elements. There is no list.
Is that just what a list with a single component comes out like? Does a list with two components come out like
{"SubtaskType":[{"id":"4","name":"mozaika","metric":"m2","code":"104"},{"name":"bb","metric":"m","id":2,"code":300}}
If this is the case, and you must receive such poorly-generated* JSON, and you must use Gson, then you'll have to implement custom deserialization processing to handle the situation where it's sometimes a list and it's sometimes an object. This is an all-too-often occurring problem. Gson unfortunately does not yet have a simple configuration available to handle this often-occurring problem. I posted an example of such custom deserialization processing in response to the question at Parsing JSON with GSON, object sometimes contains list sometimes contains object
* Just because it's valid JSON, doesn't mean it's not crap. An API should generate consistently-structured JSON. Anything less is crap.
GSON's output of List looks like:
[{"name":"aa","metric":"m2","id":1,"code":200},{"name":"bb","metric":"m","id":2,"code":300}]
Good. That's what a list in JSON is supposed to look like.
Is there a way to configure GSON to parse/generate the longer form (with type name)?
Yes. The specific solution depends on what your Java data structure currently looks like, and whether you're able to change the structure to match the desired JSON. If you cannot change the Java data structure accordingly, then you must custom process serialization/deserialization. Post the Java data structure you'd like to use, and indicate whether it can be changed.
Also, post an exact example of the "longer form" JSON you want to generate that represents a list with at least two components. You have not done this, yet. So, it leaves me guessing about what you really want to do.
It does seem pretty clear that you want polymorphic type handling in whatever the ultimate solution is. This will require custom deserialization processing, if using Gson.
Regarding any question on polymorphic deserialization, please note that the issue was discussed a few times on StackOverflow.com already. I posted a link to four different such questions and answers (some with code examples) at Can I instantiate a superclass and have a particular subclass be instantiated based on the parameters supplied.
For polymorphic serialization, not only will it likely be necessary to implement custom serialization to generate the desired type element, but convincing Gson to serialize all of the fields from polymorphic types also requires custom processing. See Serializing List of Interfaces GSON for more information.