The JSON looks like this and can have none, one or more elements in the array.
{
"players":[
{
"SteamId":"hidden",
"CommunityBanned":false,
"VACBanned":false,
"NumberOfVACBans":0,
"DaysSinceLastBan":0,
"NumberOfGameBans":0,
"EconomyBan":"none"
},
{
"SteamId":"hidden",
"CommunityBanned":false,
"VACBanned":false,
"NumberOfVACBans":0,
"DaysSinceLastBan":0,
"NumberOfGameBans":0,
"EconomyBan":"none"
}
]
}
This is what I have tried so far without any success, I just end up catching exception(s).
// I fetch the JSON from a specific API through an HTTP request.
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.GET()
.header("accept", "application/json")
.uri(URI.create(URL))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
// ... and try to deserialize it
ObjectMapper mapper = new ObjectMapper();
PlayersWrapper players = mapper.readValue(response.body(), PlayersWrapper.class); // <-- fails here.
players.getPlayerBans().forEach(System.out::println);
PlayersWrapper.java After some Googling I saw some solution that used wrapper classes in some fancy way, the JSON it was used for was somewhat more complex than mine though with two-three levels of nesting. Mine is more simple.
...
public class PlayersWrapper {
List<PlayerBan> players = new ArrayList<PlayerBan>();
}
PlayerBan.java
...
public class PlayerBan {
private String SteamId;
private boolean CommunityBanned;
private boolean VACBanned;
private int NumberOfVACBans;
private int DaysSinceLastBan;
private int NumberOfGameBans;
private String EconomyBan;
}
Stacktrace
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "players" (class com.domain.steamfinder.model.PlayersWrapper), not marked as ignorable (one known property: "playerBans"])
at [Source: (String)"{"players":[{"SteamId":"hidden","CommunityBanned":false,"VACBanned":false,"NumberOfVACBans":0,"DaysSinceLastBan":0,"NumberOfGameBans":0,"EconomyBan":"none"}]}"; line: 1, column: 13] (through reference chain: com.domain.steamfinder.model.PlayersWrapper["players"])
at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:61)
at com.fasterxml.jackson.databind.DeserializationContext.handleUnknownProperty(DeserializationContext.java:1127)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:1989)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1700)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1678)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:319)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:176)
at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:322)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4674)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3629)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3597)
at com.domain.steamfinder.finder.FinderService.findUser(FinderService.java:48)
at com.domain.steamfinder.finder.FinderController.find(FinderController.java:27)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:655)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:895)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1732)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:829)
EDIT: Original problem fixed thanks to answers pointing out the incorrect naming in the wrapper class. A new problem has emerged, see updated code above and see new stacktrace below.
Stacktrace
`Unrecognized field "SteamId" (class com.domain.steamfinder.model.PlayerBan), not marked as ignorable
(7 known properties: "economyBan", "numberOfGameBans", "communityBanned", "steamId", "numberOfVACBans", "daysSinceLastBan", "vacbanned"])
...
(through reference chain: com.domain.steamfinder.model.PlayersWrapper["players"]->java.util.ArrayList[0]->com.domain.steamfinder.model.PlayerBan["SteamId"])`
CodePudding user response:
You can change the variable name to players to match the JSON, since that is what the error is complaining
public class PlayersWrapper {
List<PlayerBan> players = new ArrayList<PlayerBan>();
}
CodePudding user response:
There are a few problems with your code, your exception does not tell everything, since Jackson stops at the first problem.
The first obviously is that the json file has a array named players, but in your class you are naming your list playerBans. This can be solved in multiple ways: you either rename your List<PlayerBan> playerBans variable to players, or you annotate the variable with @JsonProperty:
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
public class PlayersWrapper {
@JsonProperty("players")
private List<PlayerBan> playerBans;
}
You may have noticed the @JsonAutoDetect annotation. This will be a problem, mainly in your PlayerBan class, since all of the member variables are private. You can tell Jackson to recognize private members by annotating your class with @JsonAutoDetect.
Moreover, the PlayerBan class will has similar problems, as the PlayersWrapper class, meaning that some members have different naming compared to what appears in the json file. You can use @JsonProperty there as well, or you can rename the member variables.
Explanation for the @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY):
The reason we need this that Jackson does not autodetect private members of a class by default. The minimum visibility of auto-detection depends on the context (usually Jackson automatically detects public members), but we can adjust to be wider, meaning that protected and private fields will be detected as well. For other visibility options, see the JsonAutoDetect.Visibility docs.
