IoanEOD
IoanEOD

Reputation: 1

Using Gson to serialize object with transient fields

I am trying to convert an object to JSON that has an InetSocketAddress instance as an attribute. The holder attribute in the InetSocketAdress is marked as transient so is ignored by Gson when serializing to JSON.

I can't remove the transient keyword as the InetSocketAddress class is built into java.net.

I have also tried to use excludeFieldsWithModifiers() for both transient and static modifiers:

final Gson gson = new GsonBuilder().excludeFieldsWithModifiers(Modifier.TRANSIENT).create();
String json = gson.toJson(registration, Registration.class);

This produces the following error:

java.lang.reflect.InaccessibleObjectException: Unable to make field private static final long java.net.InetSocketAddress.serialVersionUID accessible: module java.base does not "opens java.net" to unnamed module @3e849b9e
    at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354)
    at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)
    at java.base/java.lang.reflect.Field.checkCanSetAccessible(Field.java:178)
    at java.base/java.lang.reflect.Field.setAccessible(Field.java:172)
    at com.google.gson.internal.reflect.UnsafeReflectionAccessor.makeAccessible(UnsafeReflectionAccessor.java:44)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:159)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:102)
    at com.google.gson.Gson.getAdapter(Gson.java:489)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:117)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:166)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:102)
    at com.google.gson.Gson.getAdapter(Gson.java:489)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:117)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:166)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:102)
    at com.google.gson.Gson.getAdapter(Gson.java:489)
    at com.google.gson.Gson.toJson(Gson.java:727)
    at com.google.gson.Gson.toJson(Gson.java:714)
    at com.google.gson.Gson.toJson(Gson.java:669)
    at org.eclipse.leshan.server.demo.websocket.WebSocketClient$1.registered(WebSocketClient.java:61)
    at org.eclipse.leshan.server.registration.RegistrationServiceImpl.fireRegistered(RegistrationServiceImpl.java:74)
    at org.eclipse.leshan.server.registration.RegistrationHandler$1.run(RegistrationHandler.java:86)
    at org.eclipse.leshan.core.response.SendableResponse.sent(SendableResponse.java:47)
    at org.eclipse.leshan.server.californium.registration.RegisterResource.handleRegister(RegisterResource.java:195)
    at org.eclipse.leshan.server.californium.registration.RegisterResource.handlePOST(RegisterResource.java:104)
    at org.eclipse.californium.core.CoapResource.handleRequest(CoapResource.java:219)
    at org.eclipse.leshan.core.californium.LwM2mCoapResource.handleRequest(LwM2mCoapResource.java:51)
    at org.eclipse.californium.core.server.ServerMessageDeliverer.deliverRequest(ServerMessageDeliverer.java:106)
    at org.eclipse.californium.core.network.stack.BaseCoapStack$StackTopAdapter.receiveRequest(BaseCoapStack.java:207)
    at org.eclipse.californium.core.network.stack.AbstractLayer.receiveRequest(AbstractLayer.java:84)
    at org.eclipse.californium.core.network.stack.AbstractLayer.receiveRequest(AbstractLayer.java:84)
    at org.eclipse.californium.core.network.stack.BlockwiseLayer.receiveRequest(BlockwiseLayer.java:488)
    at org.eclipse.californium.core.network.stack.ReliabilityLayer.receiveRequest(ReliabilityLayer.java:296)
    at org.eclipse.californium.core.network.stack.AbstractLayer.receiveRequest(AbstractLayer.java:84)
    at org.eclipse.californium.core.network.stack.BaseCoapStack.receiveRequest(BaseCoapStack.java:140)
    at org.eclipse.californium.core.network.CoapEndpoint$1.receiveRequest(CoapEndpoint.java:302)
    at org.eclipse.californium.core.network.UdpMatcher$2.run(UdpMatcher.java:289)
    at org.eclipse.californium.elements.util.SerialExecutor$1.run(SerialExecutor.java:290)
    at org.eclipse.californium.core.network.CoapEndpoint$6.run(CoapEndpoint.java:1311)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
    at java.base/java.lang.Thread.run(Thread.java:833)

How can I fix this?

Upvotes: 0

Views: 845

Answers (2)

Marcono1234
Marcono1234

Reputation: 6884

The underlying issue here is that you are (implicitly) using the reflection based Gson type adapter for the private fields of a third-party class (in this case a JDK class). This way you make yourself dependent on the implementation details of that class, which could change at any point, or as seen here can become inaccessible.

The 'correct' and future-proof solution here is to write a custom TypeAdapter for the InetSocketAdress class.

Upvotes: 0

Goutham
Goutham

Reputation: 347

The real problem is that gson library internally uses reflection strategy to access private fields. In java 9 and above, you are not allowed to access private using reflections.

One Possible solution is, Check what java version you are using. If it's Java 9 or above, then try to degrade to java 8.

Upvotes: 0

Related Questions