Gson 反序列化 json。java.lang.RuntimeException: 无法调用 public com.derp.procedure.model.SkeletonElement() 没有 args] 根本原因

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27572831/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 12:01:28  来源:igfitidea点击:

Gson deserialize json. java.lang.RuntimeException: Failed to invoke public com.derp.procedure.model.SkeletonElement() with no args] with root cause

javajsonspringgson

提问by masterdany88

It is my first time with json and java. I've check a lot of question/ post with the same error like mine. But haven't find anything usefull.

这是我第一次使用 json 和 java。我已经检查了很多问题/帖子,但与我的错误相同。但是没有找到有用的东西。

I've uderstood that I have to add no args constructor. I've maded, but it didnt helped me. Still the same error occur. It can work that way. I think that is related with quite complecated iheritance of mine code.

我已经理解我必须不添加 args 构造函数。我做了,但它没有帮助我。仍然发生同样的错误。它可以这样工作。我认为这与我的代码相当复杂的继承有关。

ERROR:

错误:

SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/derp] threw exception [Request processing failed; nested exception is java.lang.RuntimeException: Failed to invoke public com.derp.procedure.model.SkeletonElement() with no args] with root cause java.lang.InstantiationException

StackTrace:

堆栈跟踪:

gru 19, 2014 8:27:50 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/derp] threw exception [Request processing failed; nested exception is java.lang.RuntimeException: Failed to invoke public com.derp.procedure.model.SkeletonElement() with no args] with root cause
java.lang.InstantiationException
    at sun.reflect.InstantiationExceptionConstructorAccessorImpl.newInstance(InstantiationExceptionConstructorAccessorImpl.java:48)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:408)
    at com.google.gson.internal.ConstructorConstructor.construct(ConstructorConstructor.java:104)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:186)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:40)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:81)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:60)
    at com.google.gson.Gson.fromJson(Gson.java:810)
    at com.google.gson.Gson.fromJson(Gson.java:775)
    at com.google.gson.Gson.fromJson(Gson.java:724)
    at com.derp.procedure.model.SkeletonElement.toObject(SkeletonElement.java:38)
    at com.derp.procedure.model.Skeleton.setSkeletonElements(Skeleton.java:53)
    at com.derp.procedure.controller.ProcedureController.elementsAssignmentSubmit(ProcedureController.java:81)
    at com.derp.procedure.controller.ProcedureController$$FastClassBySpringCGLIB$de90ba.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:717)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
    at org.springframework.transaction.interceptor.TransactionInterceptor.proceedWithInvocation(TransactionInterceptor.java:98)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:266)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653)
    at com.derp.procedure.controller.ProcedureController$$EnhancerBySpringCGLIB$$fe2945ed.elementsAssignmentSubmit(<generated>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:215)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:781)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:721)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
    at org.springframework.web.servlet.FrameworkServlet.doPut(FrameworkServlet.java:879)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:503)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:136)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:526)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1078)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:655)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:146)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:279)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)

My java classes:

我的Java类:

Generic model class that is extended:

扩展的通用模型类:

package com.derp.generic.model;

import java.io.IOException;

import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.Transient;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.codehaus.Hymanson.JsonGenerationException;
import org.codehaus.Hymanson.annotate.JsonMethod;
import org.codehaus.Hymanson.annotate.JsonAutoDetect.Visibility;
import org.codehaus.Hymanson.map.JsonMappingException;
import org.codehaus.Hymanson.map.ObjectMapper;

@MappedSuperclass
public abstract class GenericModel<T extends GenericModel<?>> {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;


    public long getId() {return id;}
    public void setId(long id) {this.id = id;}

    public GenericModel() {
    }
    // a toString method that can be used in any class.
    // uses reflection to dynamically print java class field
    // values one line at a time.
    @Override
    public String toString() {
      return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
    }
    public String toJson() {
        ObjectMapper jsonMapper = new ObjectMapper();
        try {
            return jsonMapper.writerWithDefaultPrettyPrinter().writeValueAsString(this);
        } catch (JsonGenerationException e) {
            e.printStackTrace();
            return null;
        } catch (JsonMappingException e) {
            e.printStackTrace();
            return null;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
    //public GenericModel<T> toObject(String jsonObject) {
        //Suggested by stackOverflowComunity at:
        //https://stackoverflow.com/questions/27532206/java-create-list-of-objects-from-json-string-with-Hymanson
        public <T> T toObject(String jsonObject) {
        ObjectMapper jsonMapper = new ObjectMapper();
        try {
            //GenericModel<T> t = jsonMapper.readValue(jsonObject, GenericModel.class);
            T t = (T) jsonMapper.readValue(jsonObject, GenericModel.class);
            //return t;
            return t;
        } catch (JsonGenerationException e) {
            e.printStackTrace();
            return null;
        } catch (JsonMappingException e) {
            e.printStackTrace();
            return null;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

}   

Generic hierarchical class that extends generic model:

扩展通用模型的通用分层类:

package com.derp.generic.model;

import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.FetchType;
import javax.persistence.ManyToOne;
import javax.persistence.MappedSuperclass;
import javax.persistence.OneToMany;

import org.codehaus.Hymanson.JsonGenerationException;
import org.codehaus.Hymanson.map.JsonMappingException;
import org.codehaus.Hymanson.map.ObjectMapper;



@MappedSuperclass
public abstract class GenericHierarchicalModel<T extends GenericHierarchicalModel<T>> extends GenericModel<T> {
    private String name;
    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private T parent;
    @OneToMany(mappedBy = "parent")
    private List<T> children;

    public String getName() {return name;}
    public void setName(String name) {this.name = name;}
    public T getParent() {return parent;}
    public void setParent(T parent) {this.parent = parent;}
    public List<T> getChildren() {return children;}
    public void setChildren(List<T> children) {this.children = children;}

    public GenericHierarchicalModel() {
        super();
    }
    @Override
    public String toJson() {
        return "{\"title\":\"" + this.name + "\", \"id\":\"" + this.getId() + "\", \"children\": [" + listToJson(this.getChildren()) + "]}";
    }
    public String listToJson(List<T> children) {
        String json = "";
        for(int i=0; i<children.size(); i++) {
            json = json + children.get(i).toJson();
            if(children.size()!=i+1) {
                json = json + ", ";
            }
        }
        return json;
    }
//  @Override
//  public GenericHierarchicalModel<T> toObject(String jsonObject) {
//      int start = 0; // '(' position in string
//      int end = 0; // ')' position in string
//      for(int i = 0; i < jsonObject.length(); i++) { 
//          if(jsonObject.charAt(i) == '{') // Looking for '{' position in string
//             start = i;
//          else if(jsonObject.charAt(i) == '}') // Looking for '}' position in  string
//             end = i;
//      }
//      String number = jsonObject.substring(start+1, end); // you take value between start and end
//      System.out.println(number);
//      return null;
//  }
}

Model class that I am trying to deserialize from json list of objects:

我试图从 json 对象列表反序列化的模型类:

package com.derp.procedure.model;

import java.io.IOException;
import java.util.List;

import javax.persistence.DiscriminatorColumn;
import javax.persistence.Entity;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.codehaus.Hymanson.JsonGenerationException;
import org.codehaus.Hymanson.map.JsonMappingException;
import org.codehaus.Hymanson.map.ObjectMapper;

import com.derp.generic.model.GenericHierarchicalModel;
import com.derp.generic.model.GenericModel;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

@Entity
@Table(name="procedure__SkeletonElement")
@Inheritance(strategy=InheritanceType.JOINED)
@DiscriminatorColumn(name="type")
public abstract class SkeletonElement extends GenericHierarchicalModel<SkeletonElement> {
    @Transient
    public String getDecriminatorValue() {
        return this.getClass().getSimpleName();
    }
    @Override
    public String toJson() {
        return "{\"title\":\"" + this.getName() + "\", \"id\":\"" + this.getId() + "\", \"type\":\"" + this.getDecriminatorValue() + "\", \"children\": [" + listToJson(this.getChildren()) + "]}";
    }
    public List<SkeletonElement> toObject(String jsonObject) {
        Gson gson = new Gson(); // Or use new GsonBuilder().create();
        //SkeletonElement[] target2 = gson.fromJson(jsonObject, SkeletonElement[].class);
        List<SkeletonElement> target2 = gson.fromJson(jsonObject, new TypeToken<List<SkeletonElement>>(){}.getType());

        return target2;
    }
    public SkeletonElement() {
        super();
    }
}

And the class that contain collection of object that I am trying to deserialize back to java list of objects:

以及包含我试图反序列化回 java 对象列表的对象集合的类:

package com.derp.procedure.model;

import java.util.LinkedList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

import com.derp.generic.model.GenericDictionaryModel;

@Entity
@Table(name="procedure__Skeleton")
public class Skeleton extends GenericDictionaryModel<Skeleton> {

    @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    private List<SkeletonElement> skeletonElements;

    public void setSkeletonElements(List<SkeletonElement> skeletonElements) {this.skeletonElements = skeletonElements;}
    public List<SkeletonElement> getSkeletonElements() {return skeletonElements;}
    public List<SkeletonElement> getSkeletonParentsElements() {
        List<SkeletonElement> skeletonParentsElements = new LinkedList<SkeletonElement>();
        for(int i=0; i<this.skeletonElements.size(); i++) {
            if(this.skeletonElements.get(i).getParent()==null) {
                skeletonParentsElements.add(this.getSkeletonElements().get(i));
            }
        }
        return skeletonParentsElements;
    }

    public Skeleton(String name) {
        super(name);
    }

    public Skeleton() {
        // TODO Auto-generated constructor stub
    }

    public String getSkeletonElementsJsonTree() {
        String jsonTreeString ="[";
        List<SkeletonElement> skeletonParentsElements = getSkeletonParentsElements();
        for(int i=0; i<skeletonParentsElements.size(); i++) {
            jsonTreeString = jsonTreeString + skeletonParentsElements.get(i).toJson();
            if((1+i) != skeletonParentsElements.size()) {
                jsonTreeString = jsonTreeString + ",";
            }
        }
        return jsonTreeString + "]";
    }
    public void setSkeletonElements(String skeletonElementsJson) {
        this.skeletonElements.get(0).toObject(skeletonElementsJson);
    }



}

And at least my json string that I wont to deserialize:

至少我不会反序列化我的 json 字符串:

[
    {
        "name": "Title1",
        "id": "1",
        "type": "SkeletonJobElement",
        "parent_id": "null",
        "children": [
            {
                "name": "Title11",
                "id": "2",
                "type": "SkeletonJobElement",
                "parent_id": "1",
                "children": [
                    {
                        "name": "Title111",
                        "id": "5",
                        "type": "SkeletonFileElement",
                        "parent_id": "2",
                        "children": []
                    },
                    {
                        "name": "Title112",
                        "id": "6",
                        "type": "SkeletonFileElement",
                        "parent_id": "2",
                        "children": []
                    }
                ]
            }
        ]
    },
    {
        "name": "Title2",
        "id": "3",
        "type": "SkeletonJobElement",
        "parent_id": "null",
        "children": [
            {
                "name": "Title21",
                "id": "4",
                "type": "SkeletonJobElement",
                "parent_id": "3",
                "children": []
            }
        ]
    }
]

I know that is a lot of code to analize, but please help me figure it out. I struggle with it for week so long.

我知道有很多代码需要分析,但请帮我弄清楚。我为此挣扎了一周。

采纳答案by Ansemo Abadía

com.derp.procedure.model.SkeletonElementis an abstract class. Make this class concrete deleting the abstract modifier.

com.derp.procedure.model.SkeletonElement是一个抽象类。使这个类具体删除抽象修饰符。

回答by nejckorasa

If you want to keep class abstract, you need to write custom deserialization using Gson's JsonDeserializerand register it as type adapter. So let's say you have abstract class Aand derived class B(Bextends A):

如果要保持类抽象,则需要使用 Gson 编写自定义反序列化JsonDeserializer并将其注册为类型适配器。因此,假设您有抽象类A和派生类BBextends A):

JsonDeserializer<A> deserializer = ...; 
gsonBuilder.registerTypeAdapter(A.class, deserializer);

Now inside JsonDeserializeryou have to specify that Ashould deserialize into B:

现在在里面JsonDeserializer你必须指定A应该反序列化为B

return context.deserialize(json, B.class);

That makes more sense if you have multiple classes that derive from abstract class A. Let's say that both Band Cderive from A. In that scenario you would need to handle deserialization for both of them (inside JsonDeserializer<A>):

如果您有多个从抽象类派生的类,这更有意义A。假设BC都源自A。在那种情况下,您需要为它们(内部JsonDeserializer<A>)处理反序列化:

if (json is of class B) {
  return context.deserialize(json, B.class);
}
if (json is of class C) {
  return context.deserialize(json, C.class);
}
...

回答by dphans

If you using Kotlin, also change from abstractclass into openclass, will solve problem.

如果你使用 Kotlin,也从abstract类变为open类,将解决问题。