Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request: add an optional fallback type parameter for the toplevel json container to JsonReader.jsonToJava(json); #15

Closed
reuschling opened this issue Jul 8, 2014 · 7 comments
Assignees

Comments

@reuschling
Copy link
Contributor

We give the possibility to specify http get parameters also as json strings, to allow class objects as parameter types for the web interfaces also.

The problem is, by using json-io, specifying @type in the json string is mandatory for deserialization, right? Thus, the users have to specify it, which is not so nice (for the return values its fine of course, but for parameters?)

I love the way json-io deals with types, for me, it is the best solution to support polymorphism I have seen in such a library. Nevertheless, in this case, the underlying type of the parameter normally not changes - it should be transparent for the (e.g. javascript) user of the interface who creates the json, and clear for the server.

Is it possible to add another method to JsonReader.jsonToJava(String json, Class toplevelFallbackType) - where toplevelFallbackType could be also String, Type, etc. of course.
This parameter would then be used as fallback if the @type was not specified in the toplevel json object.
I know this would not work with polymorphism, but it would help us a lot and would be maybe a nice enhanchement of json-ios functionality:)

Thanks and best regards

Christian

@reuschling
Copy link
Contributor Author

Successfully, I have found a solution - I write it as comment if somebody has the same problem and you don't want to add this feature:

   JsonObject jsonObject = (JsonObject) JsonReader.jsonToMaps(jsonString);
   if(jsonObject.getType() == null) jsonObject.setType("package.FallbackClassName");
   Object finalJavaObject = new JsonReader().jsonObjectsToJava(jsonObject);

Thanks again for this nice piece of work!
Caution/update: The object references will be broken with this snippet. In the case you generate a json string out of a container with an object reference (an object with appears twice or more), it will become 2 seperate Objects in the final, deserialized Object. I subclassed now JsonReader with forbidden reflection Api also to achieve this functionality.

@reuschling
Copy link
Contributor Author

...as far as I found a solution for reading those json-Strings without toplevel type, it is a bit hard to create those with json-io. I did so with Collections and Arrays, by subclassing JsonWriter, adding a method write(Object obj, boolean showTopLevelType). This method simply adds the possibility to specify the 'showType' parameter in the writeImpl invocation - everything else is identical to the origin write(Object obj) method.
Sadly, I had to use forbidden reflection API to make this invocations in the subclass, because some fields and methods are declared private.
For this, I want to ask whether these elements of JsonWriter could be declared protected, to enable better subclassing of JsonWriter:

  • traceReferences
  • _objVisited
  • writeImpl
  • _objsReferenced
  • _args

Thanks a lot

@jdereg
Copy link
Owner

jdereg commented Jul 10, 2014

@type is not mandetory to be specified in the JSON. There are many circumstances where you can leave it out:

In the case of any field of an object, the @type parameter can be left off, if the value associated to the field is the exact same type of the field (usually the case). When the JSON reader encounters JSON data without the @type, it looks at the field of the object, and instantiates the object as the field type in that case. Where this does not work, is when the field is an abstract class or interface. There is special handling for the Collection classes (intelligent Collection and Map types are used). @type is also required when the field type is a superclass of the actual type written. For example, if you a class Person and Employee is derived from Person. If the field type is Person but it is polymorphically pointing to an Employee, and the @type is not written, then the JsonReader cannot instantiate the class as an Employee, as it does not know that what to instantiate. The best it could do is instantiate a Person. If person is concrete, then it will instantiate it as Person, and the Employee fields would be dropped (not desired). JsonWriter allows compares the instance type to the field type and does NOT write the @type out in these cases, so that the resulting JSON is smaller.

Another case where @type can be dropped is when you have a specific array type. An Employee[] of Employee objects. In this case, the @type, if missing on the Employee objects inside the array, will be inferred from the type of the Array. However, if the array was an Object[], then it cannot make this inference. JsonWriter compares the Objects inside an array [] when writing them, and drops the @type in this case to make the resulting JSON smaller.

@type can be left off of Object[] of Strings, Object[] of longs, Object[] of booleans, Object[] of doubles. In all those cases, it can infer the type. Furthermore, these can be placed into the JSON as their native types, as opposed to JSON Objects{} in this case. JsonWriter special handles these types so that they are written as JSON primitives (long, double, String, boolean).

@jdereg
Copy link
Owner

jdereg commented Jul 10, 2014

I can make requested APIs protected to allow for subclassing. In the next release of json-io I may change that. I want to stew on this a little bit. For now, use Reflection like you did, as those APIs are not likely changing and your code will be fine.

@reuschling
Copy link
Contributor Author

Thanks for clarification jdereg!

@jdereg jdereg closed this as completed Jul 10, 2014
@graphex
Copy link

graphex commented Aug 27, 2014

It would certainly be nice to completely turn off @type writing by using an optionalArgs value. Frequently, the receiver isn't even using java and @type has no meaning for writing purely informational files.

@jdereg jdereg reopened this Jun 22, 2015
@jdereg
Copy link
Owner

jdereg commented Jun 22, 2015

The optionalArg TYPE parameter was just added in json-io 4.0.1 which allows the @type to be completely turned off. This will create JSON that can be sent to Javascript, however, the created JSON may often not be properly reconstructed as a Java graph. The option does add utility, for instance, sending JSON to a non-Java destination.

@jdereg jdereg closed this as completed Jun 22, 2015
@jdereg jdereg self-assigned this Jun 22, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants