LinkedMultiValueMap SpringFramework 不迭代(错误:无法转换为类)

huangapple go评论170阅读模式
英文:

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(&quot;unchecked&quot;)
final LinkedMultiValueMap&lt;Integer, CSVModelAttributes&gt; attrib = new Gson().fromJson(
(csvModel.get().getAttributes()), LinkedMultiValueMap.class);

This line has a problem.

{0=[{&quot;key&quot;:&quot;customerId&quot;,&quot;value&quot;:&quot;4891&quot;}, {&quot;key&quot;:&quot;companyName&quot;,&quot;value&quot;:&quot;GIOVANE FERREIRA&quot;}, {&quot;key&quot;:&quot;place&quot;,&quot;value&quot;:&quot;AV  AV TEPEQUEM                   SN&quot;}, {&quot;key&quot;:&quot;neighborhood&quot;,&quot;value&quot;:&quot;CENTRO&quot;}, {&quot;key&quot;:&quot;city&quot;,&quot;value&quot;:&quot;AMAJARI&quot;}, {&quot;key&quot;:&quot;a&quot;,&quot;value&quot;:&quot;RR&quot;}, {&quot;key&quot;:&quot;postalCode&quot;,&quot;value&quot;:&quot;69300000&quot;}, {&quot;key&quot;:&quot;c&quot;,&quot;value&quot;:&quot;ISENTO&quot;}, {&quot;key&quot;:&quot;tradeName&quot;,&quot;value&quot;:&quot;CIA DO GELO&quot;}, {&quot;key&quot;:&quot;sectorId&quot;,&quot;value&quot;:&quot;301&quot;}, {&quot;key&quot;:&quot;region&quot;,&quot;value&quot;:&quot;RR&quot;}]}

The deserialized message has different data types then you're trying to typecast.

LinkedMultiValueMap&lt;Integer, Object&gt; linkedHashMap = (LinkedMultiValueMap&lt;Integer, Object&gt;)(new Gson().fromJson(json,LinkedMultiValueMap.class));
for(Entry&lt;Integer, List&lt;Object&gt;&gt; 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&lt;Integer, CSVModelAttributes&gt; {}

Usage:

 String json =
&quot;{0=[{\&quot;key\&quot;:\&quot;customerId\&quot;,\&quot;value\&quot;:\&quot;4891\&quot;}, {\&quot;key\&quot;:\&quot;companyName\&quot;,\&quot;value\&quot;:\&quot;GIOVANE FERREIRA\&quot;}, {\&quot;key\&quot;:\&quot;place\&quot;,\&quot;value\&quot;:\&quot;AV  AV TEPEQUEM                   SN\&quot;}, {\&quot;key\&quot;:\&quot;neighborhood\&quot;,\&quot;value\&quot;:\&quot;CENTRO\&quot;}, {\&quot;key\&quot;:\&quot;city\&quot;,\&quot;value\&quot;:\&quot;AMAJARI\&quot;}, {\&quot;key\&quot;:\&quot;a\&quot;,\&quot;value\&quot;:\&quot;RR\&quot;}, {\&quot;key\&quot;:\&quot;postalCode\&quot;,\&quot;value\&quot;:\&quot;69300000\&quot;}, {\&quot;key\&quot;:\&quot;c\&quot;,\&quot;value\&quot;:\&quot;ISENTO\&quot;}, {\&quot;key\&quot;:\&quot;tradeName\&quot;,\&quot;value\&quot;:\&quot;CIA DO GELO\&quot;}, {\&quot;key\&quot;:\&quot;sectorId\&quot;,\&quot;value\&quot;:\&quot;301\&quot;}, {\&quot;key\&quot;:\&quot;region\&quot;,\&quot;value\&quot;:\&quot;RR\&quot;}]}&quot;;
CsvModels models = (new Gson().fromJson(json, CsvModels.class));
for (Entry&lt;Integer, List&lt;CSVModelAttributes&gt;&gt; entry : models.entrySet()) {
System.out.println(entry.getKey());
for (CSVModelAttributes attributes : entry.getValue()) {
System.out.println(&quot;\t&quot; + attributes);
}
}

答案2

得分: 1

我尝试使用Junits运行了您的代码。

并且它显示出了完全正常的结果。

所以现在我看到两个可能的问题。

  1. 您正在使用的Gson版本可能存在一些问题。
  2. 您从实体中获取的字符串可能不正确。

您可以请检查这两个方面吗?

英文:

I tried running your code using Junits.

LinkedMultiValueMap SpringFramework 不迭代(错误:无法转换为类)

And it shows perfectly fine results.

LinkedMultiValueMap SpringFramework 不迭代(错误:无法转换为类)

So Now I see two possible issues.

  1. The Gson version you are using might have some problems.
  2. The String that you get from the entity might be incorrect.

Can you please check both of those things?

答案3

得分: 1

这是有问题的代码行:

final LinkedMultiValueMap&lt;Integer, CSVModelAttributes&gt; attrib = new Gson().fromJson(
      (csvModel.get().getAttributes()), LinkedMultiValueMap.class);

Gson不知道您想要的值所在的类类型。它只知道需要创建一个LinkedMultiValueMap。尝试类似以下方式:

Type mapType = new TypeToken&lt;LinkedMultiValueMap&lt;Integer, CSVModelAttributes&gt;&gt;(){}.getType();
attrib = new Gson().fromJson(csvModel.get().getAttributes()), mapType );

也可以在这里查看

英文:

This is the problematic line:

final LinkedMultiValueMap&lt;Integer, CSVModelAttributes&gt; 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&lt;LinkedMultiValueMap&lt;Integer, CSVModelAttributes&gt;&gt;(){}.getType();
attrib = new Gson().fromJson(csvModel.get().getAttributes()), mapType );

See here also

huangapple
  • 本文由 发表于 2020年8月12日 19:21:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/63375447.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定