-
Notifications
You must be signed in to change notification settings - Fork 39
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
JSON-B should process any field/method with JSON-B annotations regardless of visibility #61
Comments
|
Given the field/method visibility restrictions added in Java 9, I do not think it would be a good idea to encourage users to expose non-accessible fields/methods which would require reflection hacks by a JSON-B implementation. Closing this issue, but CC @m0mus in case you would like to argue further in favor of this. |
It's still possible to access private fields in JDK > 8. I still think that this is a valuable feature. Sometimes it makes sense initialize an immutable object from JSON. This feature can help here. Reopening. |
My worry about this feature is to start getting conflicts with visibility SPI and therefore not being able to modify the visibility from the SPI which should always win - to enable it to be dynamic by deployment/config - and when you make it win then respecting the static model (vs dynamic) is a pain for end users. Wdyt? |
Visibility SPI is not supported by the spec (yet?). So, there is no issue for now. I actually don't see an issue here at all. As we started discussing here #88 we will extend JsonbConfig and allow to configure all customizations provided by annotations now. It should include visibility tuning functionality too. We will also allow reading configuration from external sources using MP Config. Please correct me if I'm wrong, but I think that MP Config supports adding config sources using SPI. |
It is only possible in JDK > 8 because
APIs and libraries should be moving away from illegal access behavior, not toward it. |
@aguibert no, you can configure it in your module-info too....this would break all libraries otherwise ;). See open module or opens |
true... all of my experience with Java modules has been about compatibility and making things work as-is, but once java modules are more properly adopted then people will have the "opens" option in their module-info. Regarding Romain's concerns about collision with the visibility SPI, I think we can make this change in a way that is non-breaking, and update the spec/javadoc accordingly to define what happens in the case of conceptual conflicts in property visibility. I propose the following visibility resolution priority:
|
3 likely need to be adjusted to today's behavior (from memory it is public or protected for fields). Enabling the following use cases sounds like a counter productive solution:
wdyt? I would also highlight that if we solve the metamodel issue then this issue is a detail and does not need anything - in pseudo code and inspired from CDI metamodel:
|
If I'm reading this correctly, your proposed change is to consider ANY JSON-B annotation as making a property visible-by-default rather than just the
All of those examples look fine to me, and seems to be what Dmitry is proposing we do here. Can you elaborate on why you think those code examples are counter productive? |
Almost, it also require the property to be public somehow and we would read jsonb annotation on private fields if getter/setter is public/protected (already taken into account). Fully private properties stay ignored as expected to not have half of properties serialized and not the other half ignored which is a pain. We use convention over config and this would break this good pattern. |
Updating this issue to cover JSON-B annotations in general so it also encompasses |
Please also consider deserializing final fields. It allows us to think about the code in an immutable way once the object is correctly constructed by JSON-B. Both Jackson and Gson allow to deserialize final fields. |
@rdehuyss is @JsonbCreator just missing to deserialize null for you, cause JSONB already supports that? |
Well, I cannot use @JsonbCreator as I develop a library (https://github.com/jobrunr/jobrunr) that supports Gson, Jackson and (almost there) also Json-B. I prefer not to have 3 types of annotation on my model so all serializing is done either out-of-the-box or using custom serializers/deserializers/adapters. I only have compile time dependencies on the JSON-B api and it is up to the consumer to select one of these JSON libs. |
@rdehuyss then not sure what you miss since a custom deserializer or custom adapter (or even adding annotation since annotations are ignored if missing in the classloader) solutions works. Back to this issue Im concerned about an inconsistent programming model if we do it.
Is no more equivalent to
So issue is either to consider private fields by default or not IMHO but not to have activator annotations. |
Wait, let me give a test case to show what I mean:
Since I'm working on a multi-threaded library, the final help me assure that I don't make silly mistakes :-) ... however, when I want to support Jsonb (Yasson), I need to remove all the final Modifiers. I prefer to keep those. The line causing the issue (in Yassin) is https://github.com/eclipse-ee4j/yasson/blob/master/src/main/java/org/eclipse/yasson/internal/model/PropertyValuePropagation.java#L103 Does this make sense? |
The same is happening in Johnzon: https://github.com/apache/johnzon/blob/master/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAccessMode.java#L88 When writing, includeFinalFields is false and they are thus not deserialized. Could there be a strategy just like the PropertyVisibilityStrategy? |
@rdebusscher well, as mentionned, it is solved by @JsonbCreator and if you don't want it you can add a custom deserializer/adapter to handle it as you mentionned. Final fields will never be taken for deserialization since we can't set it portably but constructor or factory methods are the only ones you can use. Typically for johnzon this is not the line you mentionned but this method https://github.com/apache/johnzon/blob/master/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JsonbAccessMode.java#L185. side note about johnzon: johnzon has an interesting mode, if you drop your default constructor (which makes the jsonb model invalid since without an explicit @JsonbCreator it defaults to the no-arg constructor so it shouldn't be needed at all, in particular with final fields), then you can use @ConstructorProperties to deserialize the model. It enables to be a bit more portable. Now back to the need, it sounds to me that your need is related to the ability to decorate the model programmatically - we have others issues about it - which sounds to me more elegant than having an ad-hoc SPI for that particular feature. Otherwise - in case you can decorate explicitly your model - you don't need it at all since your constructor is public. Side note: i'll just repeat cause rereading one of your previous comment i'm not sure it is obvious, you can put jackson+gson+jsonb annotations on your model and keep these dependencies in scope provided to let the consumer pick only one, it works well thanks to the way java loads annotations. |
There are situations where mapping frameworks should legitimately access private fields. Take note that there are other libraries handling the problem, for example Hibernate JPA implementation, read https://in.relation.to/2017/04/11/accessing-private-state-of-java-9-modules/ I don't know what route they took, but I really prefer the |
Think the issue is more about including a |
Actually I agree with @rdehuyss when you want to have your object immutable your forced to do more or less a manual mapping via a custom adapter or This kind of solution is also quite fragile when you think about renaming fields. |
@asbachb well there are multiple points:
|
@JsonbProperty annotation if put on not public field/getter/setter must automatically make it visible for JSON-B engine.
The text was updated successfully, but these errors were encountered: