英文:
LinkedMultiValueMap SpringFramework not iterating (error: cannot be cast to class)
问题
Here is the translated content without the code:
I tried to iterate a springframework.LinkedMultiValueMap using different methods like iterator, foreach, stream.foreach, while, collections.values().foreach, and even a joke about sudoku, but I keep getting the error: "cannot be cast to class."
The error is occurring in the following code:
java.lang.ClassCastException: class com.google.gson.internal.LinkedTreeMap cannot be cast to class com.br.aloi.planner.model.CSVModelAttributes
It seems to be an issue with casting, and you've mentioned considering switching to the Apache Commons Collection library after two days without a solution.
英文:
I tryed to iterate a springframework.LinkedMultiValueMap, using:
- iterator
- foreach
- stream.foreach
- while
- collections.values().foreach
- sudoku(kidding)
But successively gets the error: cannot be cast to class
Here is the code:
package com.br.aloi.planner.controller;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import com.br.aloi.planner.model.CSVModel;
import com.br.aloi.planner.model.CSVModelAttributes;
import com.br.aloi.planner.service.CSVService;
import com.br.aloi.planner.service.MapsApiService;
import com.google.gson.Gson;
import com.google.gson.JsonParser;
import com.google.maps.errors.ApiException;
@Controller
public class CustomerController {
String query;
@Autowired
private CSVService CSVservice;
@GetMapping("/planner")
public ModelAndView getPlanner(
@RequestParam(value = "sortBy", defaultValue = "id", required = false) String sortParam,
@RequestParam(value = "action", required = false) Optional<String> action)
throws ApiException, InterruptedException, IOException {
ModelAndView mv = new ModelAndView("/planner");
Optional<CSVModel> csvModel = CSVservice.findById(0); //0 is just for test the linkedvaluemap
/* this is the linkedvaluemap. Created converting a
"json linkedvaluemap string" to a linkedvaluemap, with gson's help. */
@SuppressWarnings("unchecked")
final LinkedMultiValueMap<Integer, CSVModelAttributes> attrib = new Gson().fromJson(
(csvModel.get().getAttributes()), LinkedMultiValueMap.class);
/* HERE i create a collection only with the values of each entry
of linkedvaluemap. the values are a list of CSVModelAttributes */
Collection<List<CSVModelAttributes>> valuesOfAttrib = attrib.values();
/* HERE i run each one collections values to get the list of
CSVModelAttribues and after get the attribute getValue() of each model */
for (List<CSVModelAttributes> value : valuesOfAttrib) {
int i = 0;
while (i < value.size()) {
query += value.get(i).getValue() + "+";
i++;
}
System.out.println(query);
System.out.println(MapsApiService.getLat(query));
}
mv.addObject("csvModels", CSVservice.sortBy(csvModels, sortParam));
return mv;
}
}
THE CSVModelAttributes class
package com.br.aloi.planner.model;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import com.google.gson.Gson;
@SuppressWarnings("serial")
@Entity(name = "tbl_modelAttributes")
public class CSVModelAttributes implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column
private Integer modelId;
@Column(columnDefinition = "TEXT")
private String key;
@Column(columnDefinition = "TEXT")
private String value;
public CSVModelAttributes() {
}
public CSVModelAttributes(String key, String value) {
this.modelId = modelId;
this.key = key;
this.value = value;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getModelId() {
return modelId;
}
public void setModelId(Integer modelId) {
this.modelId = modelId;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
@Override
public String toString() {
return new Gson().toJson(this);
}
}
THE CSVModel class
package com.br.aloi.planner.model;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.validation.constraints.Size;
import lombok.AllArgsConstructor;
@SuppressWarnings("serial")
@Entity(name = "tbl_csv")
@AllArgsConstructor
public class CSVModel implements Serializable {
@Id
private Integer id;
@Column(length = 1024)
@Size(max = 1024)
private String attributes;
public CSVModel() {
}
public Integer getId() {
return id;
}
public Integer setId(Integer id) {
return this.id = id;
}
public String getAttributes() {
return attributes;
}
public void setAttributes(String attributes) {
this.attributes = attributes;
}
}
THE ERROR:
java.lang.ClassCastException: class com.google.gson.internal.LinkedTreeMap cannot be cast to class com.br.aloi.planner.model.CSVModelAttributes (com.google.gson.internal.LinkedTreeMap and com.br.aloi.planner.model.CSVModelAttributes are in unnamed module of loader 'app')
at com.br.aloi.planner.controller.CustomerController.getPlanner(CustomerController.java:63) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105) ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:879) ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793) ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:634) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.36.jar:9.0.36]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:373) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) ~[na:na]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at java.base/java.lang.Thread.run(Thread.java:832) ~[na:na]
THE JSON STRING
{0=[{"key":"customerId","value":"4891"}, {"key":"companyName","value":"GIOVANE FERREIRA"}, {"key":"place","value":"AV AV TEPEQUEM SN"}, {"key":"neighborhood","value":"CENTRO"}, {"key":"city","value":"AMAJARI"}, {"key":"a","value":"RR"}, {"key":"postalCode","value":"69300000"}, {"key":"c","value":"ISENTO"}, {"key":"tradeName","value":"CIA DO GELO"}, {"key":"sectorId","value":"301"}, {"key":"region","value":"RR"}]}
2 days on without solution, i'm almost getting rid of this library and putting the apache commons collection.
答案1
得分: 1
@SuppressWarnings("unchecked")
final LinkedMultiValueMap<Integer, CSVModelAttributes> attrib = new Gson().fromJson(
(csvModel.get().getAttributes()), LinkedMultiValueMap.class);
This line has a problem.
LinkedMultiValueMap<Integer, Object> linkedHashMap = (LinkedMultiValueMap<Integer, Object>)(new Gson().fromJson(json,LinkedMultiValueMap.class));
for(Entry<Integer, List<Object>> entry: linkedHashMap.entrySet()){
System.out.println(entry.getValue().get(0).getClass());
}
This code would print `class com.google.gson.internal.LinkedTreeMap`, this clearly says the data type in the list is something else, that's not CSVModelAttributes, in fact, it's a list of `TreeMap`.
You should define a model like this
public class CsvModels extends LinkedMultiValueMap<Integer, CSVModelAttributes> {}
Usage:
String json =
"{\"0\":[{\"key\":\"customerId\",\"value\":\"4891\"}, {\"key\":\"companyName\",\"value\":\"GIOVANE FERREIRA\"}, {\"key\":\"place\",\"value\":\"AV AV TEPEQUEM SN\"}, {\"key\":\"neighborhood\",\"value\":\"CENTRO\"}, {\"key\":\"city\",\"value\":\"AMAJARI\"}, {\"key\":\"a\",\"value\":\"RR\"}, {\"key\":\"postalCode\",\"value\":\"69300000\"}, {\"key\":\"c\",\"value\":\"ISENTO\"}, {\"key\":\"tradeName\",\"value\":\"CIA DO GELO\"}, {\"key\":\"sectorId\",\"value\":\"301\"}, {\"key\":\"region\",\"value\":\"RR\"}]}";
CsvModels models = (new Gson().fromJson(json, CsvModels.class));
for (Entry<Integer, List<CSVModelAttributes>> entry : models.entrySet()) {
System.out.println(entry.getKey());
for (CSVModelAttributes attributes : entry.getValue()) {
System.out.println("\t" + attributes);
}
}
英文:
@SuppressWarnings("unchecked")
final LinkedMultiValueMap<Integer, CSVModelAttributes> attrib = new Gson().fromJson(
(csvModel.get().getAttributes()), LinkedMultiValueMap.class);
This line has a problem.
{0=[{"key":"customerId","value":"4891"}, {"key":"companyName","value":"GIOVANE FERREIRA"}, {"key":"place","value":"AV AV TEPEQUEM SN"}, {"key":"neighborhood","value":"CENTRO"}, {"key":"city","value":"AMAJARI"}, {"key":"a","value":"RR"}, {"key":"postalCode","value":"69300000"}, {"key":"c","value":"ISENTO"}, {"key":"tradeName","value":"CIA DO GELO"}, {"key":"sectorId","value":"301"}, {"key":"region","value":"RR"}]}
The deserialized message has different data types then you're trying to typecast.
LinkedMultiValueMap<Integer, Object> linkedHashMap = (LinkedMultiValueMap<Integer, Object>)(new Gson().fromJson(json,LinkedMultiValueMap.class));
for(Entry<Integer, List<Object>> entry: linkedHashMap.entrySet()){
System.out.println(entry.getValue().get(0).getClass());
}
This code would print class com.google.gson.internal.LinkedTreeMap
, this clearly says the data type in the list is something else, that's not CSVModelAttributes, in fact, it's a list of TreeMap
.
You should define a model like this
public class CsvModels extends LinkedMultiValueMap<Integer, CSVModelAttributes> {}
Usage:
String json =
"{0=[{\"key\":\"customerId\",\"value\":\"4891\"}, {\"key\":\"companyName\",\"value\":\"GIOVANE FERREIRA\"}, {\"key\":\"place\",\"value\":\"AV AV TEPEQUEM SN\"}, {\"key\":\"neighborhood\",\"value\":\"CENTRO\"}, {\"key\":\"city\",\"value\":\"AMAJARI\"}, {\"key\":\"a\",\"value\":\"RR\"}, {\"key\":\"postalCode\",\"value\":\"69300000\"}, {\"key\":\"c\",\"value\":\"ISENTO\"}, {\"key\":\"tradeName\",\"value\":\"CIA DO GELO\"}, {\"key\":\"sectorId\",\"value\":\"301\"}, {\"key\":\"region\",\"value\":\"RR\"}]}";
CsvModels models = (new Gson().fromJson(json, CsvModels.class));
for (Entry<Integer, List<CSVModelAttributes>> entry : models.entrySet()) {
System.out.println(entry.getKey());
for (CSVModelAttributes attributes : entry.getValue()) {
System.out.println("\t" + attributes);
}
}
答案2
得分: 1
我尝试使用Junits运行了您的代码。
并且它显示出了完全正常的结果。
所以现在我看到两个可能的问题。
- 您正在使用的Gson版本可能存在一些问题。
- 您从实体中获取的字符串可能不正确。
您可以请检查这两个方面吗?
英文:
I tried running your code using Junits.
And it shows perfectly fine results.
So Now I see two possible issues.
- The Gson version you are using might have some problems.
- The String that you get from the entity might be incorrect.
Can you please check both of those things?
答案3
得分: 1
这是有问题的代码行:
final LinkedMultiValueMap<Integer, CSVModelAttributes> attrib = new Gson().fromJson(
(csvModel.get().getAttributes()), LinkedMultiValueMap.class);
Gson不知道您想要的值所在的类类型。它只知道需要创建一个LinkedMultiValueMap。尝试类似以下方式:
Type mapType = new TypeToken<LinkedMultiValueMap<Integer, CSVModelAttributes>>(){}.getType();
attrib = new Gson().fromJson(csvModel.get().getAttributes()), mapType );
英文:
This is the problematic line:
final LinkedMultiValueMap<Integer, CSVModelAttributes> attrib = new Gson().fromJson(
(csvModel.get().getAttributes()), LinkedMultiValueMap.class);
Gson doesn't known in what class-type you want your values. It just known it needs to make a LinkedMultiValueMap.
Try something like:
Type mapType = new TypeToken<LinkedMultiValueMap<Integer, CSVModelAttributes>>(){}.getType();
attrib = new Gson().fromJson(csvModel.get().getAttributes()), mapType );
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论