提问人:cloudingAround 提问时间:11/12/2023 最后编辑:cloudingAround 更新时间:11/13/2023 访问量:71
如何解决以下问题:无法写入 JSON:无法使字段“java.lang.ThreadLocal#threadLocalHashCode”可访问?
How do I fix the following issue: Could not write JSON: Failed making field 'java.lang.ThreadLocal#threadLocalHashCode' accessible?
问:
我正在尝试在spring boot中为分配构建CRUD监视列表API的创建部分。我需要将我的数据存储在 json 文件而不是数据库中,以序列化和反序列化我在将新数据添加到我的监视列表时使用 gson。
问题是当我向 API 发送发布请求时,出现以下错误:
IDE 返回以下内容:
2023-11-12T12:13:11.613Z WARN 17744 --- [nio-8080-exec-5] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Failed making field 'java.lang.ThreadLocal#threadLocalHashCode' accessible; either increase its visibility or write a custom TypeAdapter for its declaring type.]
我希望当我发送发布请求时,数据会写入 gson 文件,并将新条目附加到现有监视列表的末尾
这是我写给 gson 的代码部分:
@Service
public class WriteToJson {
private CreateWatchlist createList;
private static final Logger log = LoggerFactory.getLogger(WriteToJson.class);
@Autowired
public WriteToJson(CreateWatchlist createList) {
this.createList = createList;
}
Gson gson = new GsonBuilder().registerTypeAdapter(LocalDate.class, new DateTypeAdapter()).create();
String jsonString = gson.toJson(createList);
public void writeToJson() throws FailureToIOJsonException {
String jsonRepo = "JsonWatchlist.json";
try {
List<Watchlist> existingListData = gson.fromJson(jsonString, new TypeToken<List<Watchlist>>() {}.getType());
if(existingListData == null) {
existingListData = new ArrayList<>();
}
existingListData.add(createList);
try (FileWriter writer = new FileWriter(jsonRepo, true)) {
gson.toJson(existingListData, writer);
} catch (IOException e) {
log.error("Serialized watchlist failed to write to Json file.", e);
throw new FailureToIOJsonException("IOException occurred while attempting to write new data to JSON.", e);
}
} catch (IOException e) {
log.error("Failed to add createWatchlist to the new entry array", e);
throw new FailureToIOJsonException("Exception occurred while trying to write createWatchlist to the addEntry array.", e);
}
}
}
下面是要序列化的数据的构造函数的输入:
@Component
public class CreateWatchlist extends Watchlist{
private UUID uuid;
private String stockName;
private String symbol;
private boolean owned;
private String status;
private String currency;
private LocalDate datePurchased;
private Integer unitsOwned;
private double profit;
private double pointsChange;
private double open;
private double close;
private double intradayHigh;
public CreateWatchlist() {
super();
}
public CreateWatchlist(UUID uuid, String stockName, String symbol, boolean owned, String status, String currency,
LocalDate datePurchased, Integer unitsOwned, double profit, double pointsChange, double open, double close,
double intradayHigh) {
super();
if(uuid == null){
this.uuid = generateUUID("default");
}else{
this.uuid = uuid;
}
this.stockName = stockName;
this.symbol = symbol;
this.owned = owned;
this.status = status;
this.currency = currency;
this.datePurchased = datePurchased;
this.unitsOwned = unitsOwned;
this.profit = profit;
this.pointsChange = pointsChange;
this.open = open;
this.close = close;
this.intradayHigh = intradayHigh;
}
// public CreateWatchlist() {
// }
public UUID generateUUID(String stockName){
int stockNameCount = getStocknameincrement().getOrDefault(stockName, 0);
getStocknameincrement().put(stockName, stockNameCount + 1);
return UUID.nameUUIDFromBytes((stockName + stockNameCount).getBytes());
}
public UUID getUuid() {
return uuid;
}
public void setStockName(String stockName) {
this.stockName = stockName;
}
public String getStockName() {
return stockName;
}
public String getSymbol() {
return symbol;
}
public void setSymbol(String symbol) {
this.symbol = symbol;
}
public boolean isOwned() {
return owned;
}
public void setOwned(boolean owned) {
this.owned = owned;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getCurrency() {
return currency;
}
public void setCurrency(String currency) {
this.currency = currency;
}
public LocalDate getDatePurchased() {
return datePurchased;
}
public void setDatePurchased(LocalDate datePurchased) {
this.datePurchased = datePurchased;
}
public Integer getUnitsOwned() {
return unitsOwned;
}
public void setUnitsOwned(Integer unitsOwned) {
this.unitsOwned = unitsOwned;
}
public double getProfit() {
return profit;
}
public void setProfit(double profit) {
this.profit = profit;
}
public double getPointsChange() {
return pointsChange;
}
public void setPointsChange(double pointsChange) {
this.pointsChange = getClose() - getOpen();
}
public double getOpen() {
return open;
}
public void setOpen(double open) {
this.open = open;
}
public double getClose() {
return close;
}
public void setClose(double close) {
this.close = close;
}
public double getIntradayHigh() {
return intradayHigh;
}
public void setIntradayHigh(double intradayHigh) {
this.intradayHigh = intradayHigh;
}
@Override
public String toString() {
return "WatchlistInherited [uuid=" + uuid + ", stockName=" + stockName + ", symbol=" + symbol + ", owned=" + owned + ", status=" + status + ", currency="
+ currency + ", datePurchased=" + datePurchased + ", unitsOwned=" + unitsOwned + ", profit=" + profit
+ ", pointsChange=" + pointsChange + ", open=" + open + ", close=" + close + ", intradayHigh="
+ intradayHigh + "]";
}
}
这是我发出 POST 请求时返回的错误:
Postman 返回以下内容:
{
"timestamp": "Nov 12, 2023, 12:13:11 PM",
"status": 500,
"error": "Internal Server Error",
"trace": "org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Failed making field 'java.lang.ThreadLocal#threadLocalHashCode' accessible; either increase its visibility or write a custom TypeAdapter for its declaring type.\r\n\tat org.springframework.http.converter.json.AbstractJsonHttpMessageConverter.writeInternal(AbstractJsonHttpMessageConverter.java:128)\r\n\tat org.springframework.http.converter.AbstractGenericHttpMessageConverter.write(AbstractGenericHttpMessageConverter.java:103)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:297)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:245)\r\n\tat org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:78)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:136)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:884)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797)\r\n\tat org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)\r\n\tat org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1081)\r\n\tat org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:974)\r\n\tat org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1011)\r\n\tat org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:914)\r\n\tat jakarta.servlet.http.HttpServlet.service(HttpServlet.java:590)\r\n\tat org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885)\r\n\tat jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:205)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)\r\n\tat org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)\r\n\tat org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)\r\n\tat org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)\r\n\tat org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)\r\n\tat org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167)\r\n\tat org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90)\r\n\tat org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482)\r\n\tat org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115)\r\n\tat org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)\r\n\tat org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)\r\n\tat org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:341)\r\n\tat org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:391)\r\n\tat org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)\r\n\tat org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:894)\r\n\tat org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1740)\r\n\tat org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)\r\n\tat org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)\r\n\tat org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)\r\n\tat org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\r\n\tat java.base/java.lang.Thread.run(Thread.java:833)\r\nCaused by: com.google.gson.JsonIOException: Failed making field 'java.lang.ThreadLocal#threadLocalHashCode' accessible; either increase its visibility or write a custom TypeAdapter for its declaring type.\r\n\tat com.google.gson.internal.reflect.ReflectionHelper.makeAccessible(ReflectionHelper.java:38)\r\n\tat com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:286)\r\n\tat com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:130)\r\n\tat com.google.gson.Gson.getAdapter(Gson.java:556)\r\n\tat com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:160)\r\n\tat com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:294)\r\n\tat com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:130)\r\n\tat com.google.gson.Gson.getAdapter(Gson.java:556)\r\n\tat com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:160)\r\n\tat com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:294)\r\n\tat com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:130)\r\n\tat com.google.gson.Gson.getAdapter(Gson.java:556)\r\n\tat com.google.gson.Gson.toJson(Gson.java:834)\r\n\tat com.google.gson.Gson.toJson(Gson.java:812)\r\n\tat com.google.gson.Gson.toJson(Gson.java:783)\r\n\tat org.springframework.http.converter.json.GsonHttpMessageConverter.writeInternal(GsonHttpMessageConverter.java:106)\r\n\tat org.springframework.http.converter.json.AbstractJsonHttpMessageConverter.writeInternal(AbstractJsonHttpMessageConverter.java:125)\r\n\t... 48 more\r\nCaused by: java.lang.reflect.InaccessibleObjectException: Unable to make field private final int java.lang.ThreadLocal.threadLocalHashCode accessible: module java.base does not \"opens java.lang\" to unnamed module @5c0e7ef1\r\n\tat java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354)\r\n\tat java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)\r\n\tat java.base/java.lang.reflect.Field.checkCanSetAccessible(Field.java:178)\r\n\tat java.base/java.lang.reflect.Field.setAccessible(Field.java:172)\r\n\tat com.google.gson.internal.reflect.ReflectionHelper.makeAccessible(ReflectionHelper.java:35)\r\n\t... 64 more\r\n",
"message": "Could not write JSON: Failed making field 'java.lang.ThreadLocal#threadLocalHashCode' accessible; either increase its visibility or write a custom TypeAdapter for its declaring type.",
"path": "/watchlist/addEntry"
}
我无法找到解决此问题的方法,如果能提供任何帮助,我将不胜感激。
这是下面监视列表中的代码。当我在 postman 中发送 POST 请求时,我收到上面显示的两条消息,我将返回并突出显示它们。
public class Watchlist {
// @JsonProperty
private static final Map<String, Integer> stockNameIncrement = new HashMap<>();
public static Map<String, Integer> getStockNameIncrement() {
return stockNameIncrement;
}
}
答: 暂无答案
评论
Watchlist
ThreadLocal
FileWriter(..., append=true)
WriteToJson
ThreadLocal