When I naively use Jackson to convert to JSON i receive this exception:
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.apache.cayenne.access.DefaultDataRowStoreFactory and no properties discovered to create BeanSerializer
Edit: I'd like to do something like this:
ObjectContext context = cayenneRuntime.newContext();
List<User> users = ObjectSelect.query(User.class).select(context);
JsonObject json = Json.mapper.convertValue(obj, Map.class)
Are there any existing solutions? Thanks
Considering that in a general case Cayenne gives you not just objects, but a virtual graph of objects, serialization to JSON becomes a more quirky topic than it initially appears.
The short answer: you'd have manually build JSON for whatever subgraph of your object graph.
While not a direct answer, it may be worth mentioning that Agrest framework (ex. LinkRest) supports rule-based serialization of Cayenne object graphs to JSON. But it is not a standalone component. I.e. it will only work if you use it for your REST services.
Related
I need to parse the jax-ws rest response and I tried the following two ways of parsing the response.Both works good.But I am in need to know the best efficient way of implementation.Please provide me your view.
First Approach:
Use getEntity Object and get the response as Input Stream.
Using Jackson ObjectMapper readValue() -covert the inputstream to java
object.
Using getters and setters of nested java class get the response objects member values.
Second Approach:
Use getEntity Object and get the response as Input Stream and and
convert the Input Stream to String.
Using Google Json API,convert the string to json object.
Using Json parser and get the nested objects member values.
I would say the first approach is better for two reasons:
You don't go through the intermediate process of reading the response payload into String
The setter methods that are called during Jackson deserialization may perform validation on input and throw appropriate exceptions, so you do validation during deserialization.
Maybe not a general answer to this question but another variant of what you're describing under "First approach". I would start with a generic data structure and would only introduce an extra bean if necessary. I wouldn't use String to pass structured data around.
Use jackson to convert the JSON response to a
Map<String,Object> or JsonNode.
Advantage:
You don't need to implement a specialized bean class. Even a very simple bean can become unhandy over time (if format changes or new nested structures are added to the json response, etc.). It also introduces some kind of metaphor to your code which sometimes helps but also can be misleading.
Map<String,Object> is in the JDK and offers a good interface to access data. You don't have to change any interfaces even if the JSON format changes.
You can always pass your data in form of a Map<String,Object>
Disadvantage
Data Encapsulation. The map is a very close representation of the input data and therefore offers not same level of abstraction like a bean.
I am developing an application system that has multiple executable applications on different platforms (java and .net).
For communication between them I am using JSON format. So I need to map object to and from json very frequently. Current solution (seems workaround) is jackson at java end and Newtonsoft.Json at .NET end. Problem is property name are not same and not all properties will be required at de-serialization end
So my questions are:
1. Is there any mapper to do this.
Currently using NewtonSoft.JSON.DatasetMapper at .Net end and
jsonanysetter annotation at java, but in this approach mapping
definition is loaded for each object as actual object mapping code
is in code. For example:
//C#
myobj.prop1 = dataSet.Tables[0].Rows[0]["propertyName1"].ToString();
// and so on.....
//Java
switch(key)
{
case "prop1":
myobj.setPropery1(value.toString());
break;
//and so on......
}
2. Object transformationRate needs to be very high as object are
sent and recieved at very high speed. say some 10k objects per second.
We used GSON in one of our project , i think this reference may help you, Apart from it ,there is a similar question may help you. another q/a in stackoverflow
You should take a look at Jackson. It's the de facto JSON library for Java and will happily handle turning objects into JSON and back again. It has many options to allow you to alter the output, and most per-object configuration is carried out using annotations so is visible in your model rather than hidden away in a separate configuration file.
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 in the process of upgrading a grails plugin from 1.3.4 to grails 2.1.1. After upgrading I now have an integration test that fails that was not failing before. It fails on using the "as JSON" (grails.converters.JSON).
#Test
public void testConvertCollectionOfEnvironmentSettingsToJSON() {
EnvironmentSetting setting = configurationService.getEnvironmentSetting('ENFORCE_SCHEMA_INSTANCE_RULE')
def jsonSetting = setting as JSON //exception thrown here
def s = jsonSetting as String
assertNotNull jsonSetting
}
The exception and stacktrace:
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'com.company.ipsvc.configuration.domain.EnvironmentSettingAllRevs#48c12420' with class 'com.company.ipsvc.configuration.domain.EnvironmentSettingAllRevs' to class 'grails.converters.JSON'
at com.company.ipsvc.configuration.converter.json.basic.BasicEnvironmentSettingJSONIntegrationTests.testConvertCollectionOfEnvironmentSettingsToJSON(BasicEnvironmentSettingJSONIntegrationTests.groovy:28)
I am able to use encodeAsJSON() successfully. I also have the same issue with as XML.
I think converters (as JSON syntax) will only work on domain objects and collections by default.
To convert arbitrary objects you should use the encodeAsJSON() converter, I believe. Or use an object marshaller, where you tell the converter how to deal with your object.
The docs aren't very clear on this though..
See:
http://grails.org/Converters+Reference (object marshalling section at bottom)
http://grails.org/doc/latest/ref/Plug-ins/codecs.html
But I note that http://grails.org/doc/latest/api/grails/converters/JSON.html#JSON%28java.lang.Object%29 says that the object converts POGOs.. Maybe it means if you have a marshaller?
I did find this reference too:
Notice that the ‘as’ operator is not overloaded for plain objects ...
Domain objects can use the ‘as’ operator to cast an object to JSON, the same as a collection. So unlike POGOs, where they must be massaged into a list or have encodeAsJSON explictly called ...
http://manbuildswebsite.com/2010/02/08/rendering-json-in-grails-part-2-plain-old-groovy-objects-and-domain-objects/
Which seems to describe the situation.
For non-Domain objects, we found that this would crop up when running tests... the solution for us was to use new JSON:
render new JSON( obj )
This would allow the test to work, and the code does the same thing (essentially)
Ran into a similar issue that broke unit test using grails 2.2.1 . At issue was a straight obj as JSON conversion attempt. But this was interpreted as type casting instead.
The workaround is to stuff your obj to be converted into a map like this [data:obj] as JSON
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.