无法使字段“属性”可访问;更改其可见性或为其声明类型 gSON fromJson

问题描述 投票:0回答:6

我有一个名为游戏的课程:

public class Game {
    private String name;
    private int id;
    private GameFields[] gameFields;

    @Expose(deserialize = false)
    public ArrayList<Player> players = new ArrayList<>();

    public Game() {

    }

    public Game(String name, int id, GameFields[] gameFields) {
        this.name = name;
        this.id = id;
        this.gameFields = gameFields;
    }
}

我想使用 GSON.fromJson 方法为此类创建对象。 但问题是方法返回

Failed to make field 'com.example.Models.Game#name' accessible; either change its visibility or write a custom TypeAdapter for its declaring type

这就是我调用该方法的方式

Gson gson = new Gson();
Game object = null;
try {
    object = gson.fromJson("{\"name\":\"test\",\"id\":1}", Game.class);
}catch (JsonParseException e){
    System.out.println(e.getMessage());
}

我不知道为什么会发生这种情况,因为在我看到的每个示例中,用户都对其字段使用了私有可见性。 但就我而言,只有当我将字段的可见性更改为公共时,它才有效。

更新

整个堆栈跟踪:

com.google.gson.JsonIOException: Failed making field 'com.example.server.Models.Game#name' accessible; either change its visibility or write a custom TypeAdapter for its declaring type
    at [email protected]/com.google.gson.internal.reflect.ReflectionHelper.makeAccessible(ReflectionHelper.java:22)
    at [email protected]/com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:158)
    at [email protected]/com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:101)
    at [email protected]/com.google.gson.Gson.getAdapter(Gson.java:501)
    at [email protected]/com.google.gson.Gson.fromJson(Gson.java:990)
    at [email protected]/com.google.gson.Gson.fromJson(Gson.java:956)
    at [email protected]/com.google.gson.Gson.fromJson(Gson.java:905)
    at [email protected]/com.google.gson.Gson.fromJson(Gson.java:876)
    at com.example.server/com.example.server.Server$2.onData(Server.java:55)
    at com.example.server/com.example.server.Server$2.onData(Server.java:44)
    at [email protected]/com.corundumstudio.socketio.namespace.Namespace.onEvent(Namespace.java:146)
    at [email protected]/com.corundumstudio.socketio.handler.PacketListener.onPacket(PacketListener.java:106)
    at [email protected]/com.corundumstudio.socketio.handler.InPacketHandler.channelRead0(InPacketHandler.java:92)
    at [email protected]/com.corundumstudio.socketio.handler.InPacketHandler.channelRead0(InPacketHandler.java:36)
    at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:377)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:363)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:355)
    at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102)
    at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:377)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:363)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:355)
    at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:377)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:363)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:355)
    at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:294)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:377)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:363)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:355)
    at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:377)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:363)
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
    at [email protected]/com.corundumstudio.socketio.transport.PollingTransport.onPost(PollingTransport.java:161)
    at [email protected]/com.corundumstudio.socketio.transport.PollingTransport.handleMessage(PollingTransport.java:120)
    at [email protected]/com.corundumstudio.socketio.transport.PollingTransport.channelRead(PollingTransport.java:97)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:377)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:363)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:355)
    at [email protected]/com.corundumstudio.socketio.handler.AuthorizeHandler.channelRead(AuthorizeHandler.java:137)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:377)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:363)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:355)
    at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:102)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:377)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:363)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:355)
    at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102)
    at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:377)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:363)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:355)
    at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:377)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:363)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:355)
    at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:316)
    at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:290)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:377)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:363)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:355)
    at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:377)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:363)
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163)
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:714)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:650)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:576)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)
    at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
    at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make field private java.lang.String com.example.server.Models.Game.name accessible: module com.example.server does not "opens com.example.server.Models" to module com.google.gson
    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:180)
    at java.base/java.lang.reflect.Field.setAccessible(Field.java:174)
    at [email protected]/com.google.gson.internal.reflect.ReflectionHelper.makeAccessible(ReflectionHelper.java:19)
    ... 75 more
java gson
6个回答
9
投票

我通过添加以下行解决了问题:

opens com.example.server.Models to com.google.gson;

module-info.java


5
投票

在 java 升级版本 11 到 17 期间,我在使用 gson 反序列化 java.time.Instant 时遇到了同样的问题,请参阅 gson 文档,了解发生这种情况的原因: https://github.com/google/gson/blob/main/UserGuide.md#gsons-expose

解决方案: 使用 -

new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create()

创建 Gson

示例:

Gson gson = new GsonBuilder().setPrettyPrinting()
            .excludeFieldsWithoutExposeAnnotation()
            .create();

3
投票

我在使用 gson 反序列化 java.time.LocalDate 时遇到了同样的问题,我认为 gson 文档的这一部分揭示了发生这种情况的原因:

Gson 文档疑难解答

我引用文档:

说明:当某个类型不存在内置适配器并且没有自定义适配器时 适配器已注册,Gson 回退到使用反射来 访问类的字段(包括私有字段)。最有可能的是你 看到此错误是因为您(意外地)依赖于 用于第三方类的基于反射的适配器。那应该是 避免因为你让自己依赖于实现 这些类的详细信息可能随时发生变化。对于JDK 也不可能再使用访问内部字段 从 JDK 17 开始反射,请参阅 JEP 403。如果你想阻止 将来使用第三方类的反射你可以编写 您自己的 ReflectionAccessFilter 或使用预定义的之一, 例如ReflectionAccessFilter.BLOCK_ALL_PLATFORM。


0
投票

这可能是因为

Gson
可能无法将
Arraylists
从你的类转换为 json 字符串。因此,这就是为什么它推荐类型适配器。类型适配器基本上用于转换 gson 无法转换为 json 的类。在此适配器中,您将描述您的类应如何与 json 字符串相互转换。这是文档
另外, "{"name":"test","id":1}" 没有数组列表
GameFields
。所以,这可能是另一个错误点。


0
投票

我遇到了类似的问题,涉及更复杂的类,其中包括几个涉及反序列化的对象。通过使用

@Expose
注释显式标记类的哪些字段参与反序列化,解决了该问题。

此外,

@SerializedName
注释用于每个字段,用于字段和 JSON 元素之间的映射。


0
投票

我将发布在我类似的错误场景中对我来说完美有效的内容。

Gson customGson = new GsonBuilder()
.registerTypeAdapter(LocalDate.class, new LocalDateTypeAdapter())
.create();
String jsonString = customGson.toJson(member);
String responsePojo = customGson.fromJson(memberSearchResponse, MemberSearchResponsePojo.class);

LocalDateTypeAdapter
需要单独定义,这是您的自定义 TypeAdapter,可以按如下方式完成:

import com.google.gson.*;

import java.lang.reflect.Type;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

public class LocalDateTypeAdapter implements JsonSerializer<LocalDate>, JsonDeserializer<LocalDate> {

  private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

  @Override
  public JsonElement serialize(final LocalDate date, final Type typeOfSrc,
      final JsonSerializationContext context) {
    return new JsonPrimitive(date.format(formatter));
  }

  @Override
  public LocalDate deserialize(final JsonElement json, final Type typeOfT,
      final JsonDeserializationContext context) throws JsonParseException {
    return LocalDate.parse(json.getAsString(), formatter);
  }
}
  1. 参考链接-1
  2. 参考链接-2
  3. 参考链接-3

Reference Link-2
的这个解决方案对我有用。 您也可以尝试
module-info.java
文件解决方案方法,但不幸的是我无法使该方法为我工作。

© www.soinside.com 2019 - 2024. All rights reserved.