【IT专家】反序列化无效的类
- 格式:pdf
- 大小:315.28 KB
- 文档页数:5
本文由我司收集整编,推荐下载,如有疑问,请与我司联系在JAVA 中封装JSONUtils 工具类及使用(转)HashMap String, Object data = new HashMap String, Object (); JSONObject jsonObject = JSONUtils.toJSONObject(object); Iterator it = jsonObject.keys(); while (it.hasNext()) String key = String.valueOf(it.next()); Object value = jsonObject.get(key); data.put(key, value); return data; /*** * 将对象转换为List * @param object * @return// 返回非实体类型(Map)的List public static List Map String, Object toList(Object object) List Map String, Object list = new ArrayList Map String, Object (); JSONArray jsonArray = JSONArray.fromObject(object); for (Object obj : jsonArray) JSONObject jsonObject = (JSONObject) obj; Map String, Object map = new HashMap String, Object (); Iterator it = jsonObject.keys(); while (it.hasNext()) String key = (String) it.next(); Object value = jsonObject.get(key); map.put((String) key, value); list.add(map); return list; /*** * 将JSON 对象数组转换为传入类型的List * @param * @param jsonArray *@param objectClass * @return public static T List T toList(JSONArray jsonArray, Class T objectClass) return JSONArray.toList(jsonArray, objectClass); /*** * 将对象转换为传入类型的List * @param * @param jsonArray * @param objectClass * @return public static T List T toList(Object object, Class T objectClass) JSONArray jsonArray = JSONArray.fromObject(object); return JSONArray.toList(jsonArray, objectClass); /*** *将JSON 对象转换为传入类型的对象* @param * @param jsonObject * @param beanClass * @return public static T T toBean(JSONObject jsonObject, Class T beanClass)return (T) JSONObject.toBean(jsonObject, beanClass); /*** * 将将对象转换为传入类型的对象* @param * @param object * @param beanClass * @return public static T T toBean(Object object, Class T beanClass) JSONObject jsonObject = JSONObject.fromObject(object); return (T) JSONObject.toBean(jsonObject, beanClass); /*** * 将JSON 文本反序列化为主从关系的实体* @param 泛型T 代表主实体类型* @param 泛型D 代表从实体类型* @param jsonString JSON 文本* @param mainClass 主实体类型* @param detailName 从实体类在主实体类中的属性名称*。
使⽤Jackson反序列化遇到的问题及解决Jackson反序列化遇到的问题最近在项⽬中需要使⽤Jackson把前台转来的字符转为对象,转换过程中发⽣了错误,报错如下c om.fasterxml.jackson.databind.exc.InvalidFormatException: Can not construct instance of java.util.Date fromStringvalue '2018-09-14 15:12:08': not a valid representation (error: Failed to parse Date value '2018-09-14 15:12:08': Can not parse date "2018-09-14 15:12:08": not compatible with any of standard forms ("yyyy-MM-dd'T'HH:mm:ss.SSSZ","yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", "EEE, dd MMM yyyy HH:mm:ss zzz", "yyyy-MM-dd"))原因是需要转换成的⽬标对象有Date类型的属性,前台传来的是yyyy-MM-dd HH:mm:ss类型⽽Jackson只⽀持以下四种yyyy-MM-dd'T'HH:mm:ss.SSSZyyyy-MM-dd'T'HH:mm:ss.SSS'Z'EEE, dd MMM yyyy HH:mm:ss zzzyyyy-MM-dd在⽹上查了许多⽅法都⽐较⿇烦,我太懒……发现⽤两个注解就可以轻松解决@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")private Date createTime;JackSon反序列化时忽略对象中不存在的json字段如果json字段⽐较多,⽽我们对象只需要部分字段,这时反序列化时会报错,可以在new ObjectMapper后加上objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);就可以在反序列化时忽略json中多余的字段了。
序列化是以字节流的形式将数据保存到磁盘和从磁盘上将数据读到内存中的过程。
一、标准MFC框架程序的文件保存和读取函数:1.打开文件,参见\Microsoft Visual Studio\VC98\MFC\SRC\DOCCORE.CPP:BOOL CDocument::OnOpenDocument(LPCTSTR lpszPathName)2.保存文件,参见\Microsoft Visual Studio\VC98\MFC\SRC\DOCCORE.CPP:BOOL CDocument::OnSaveDocument(LPCTSTR lpszPathName)这两个函数实现过程类似,都是先得到一个文件指针,然后声明一个CArchive对象,之后调用Serialize函数实现序列化数据输入或输出,出于Serialize是一个虚函数,因此实际上调用的是用户程序中文档类的序列化函数。
在CDocument类中调用Serialize 函数时使用try和catch对异常情况进行处理,比如在读取文件时越界将给出提示。
二、在自己的应用程序的序列化中使用异常处理1.序列化异常类:CArchiveException,派生于CException类。
CArchiveException包含一个int类型的m_cause成员,它为以下枚举值之一:a) CArchiveException::none无错b) CArchiveException::generic一个无法识别的错误c) CArchiveException::readOnly试图写以读入方式打开的文件d) CArchiveException::endOfFile已到文件尾e) CArchiveException::writeOnly试图读以存储方式打开的文件f) CArchiveException::badIndex无效文件格式g) CArchiveException::badClass把一个对象读到错误对象类型中去h) CArchiveException::badSchema版本号错误2.抛出异常函数:void AfxThrowArchiveException(int cause,LPCTSTR lpszArchiveName = NULL);在有序列化异常发生时可使用AfxThrowArchiveException抛出异常,参数cause为异常的原因,为上面的枚举值之一,参数lpszArchiveName为档案文件名。
Jackson反序列化@JsonFormat不⽣效的解决⽅案今天在线上发现⼀个问题,在使⽤Jackson进⾏时间的反序列化时,配置的@JsonFormat没有⽣效查看源码发现,Jackson在反序列化时间时,会判断json字段值类型,如下:由于在我们服务⾥,前端传时间值到后端时采⽤了时间戳的⽅式,json值被判断为数字类型,所以Jackson在反序列化时直接简单粗暴的⽅式处理,将时间戳转换为Date类型:为了能够按照正确的格式解析时间,抹去后⾯的时间点,精确到⽇,只好⾃定义⼀个时间解析器。
⾃定义的时间解析器很好实现,⽹上已经有很多实例代码,只需要继承 JsonDeserializer<T> 就可以。
问题的关键点在于,如何获取到注解上的时间格式,按照注解上的格式去解析,否则每个解析器的实现只能使⽤⼀种固定的格式去解析时间。
1. 所以第⼀步是获取注解上配置的信息想要获取字段对应的注解信息,只有找到相应的字段,然后通过字段属性获取注解信息,再通过注解信息获取配置的格式。
但找了很久,也没有在既有的参数⾥找到获取相关字段的⽅法,只能去翻看源码,最后在这⾥发现了获取字段信息的⽅法以及解析器的⽣成过程,源代码如下:第⼀个红框表⽰解析器是在这⾥⽣成的,第⼆个红框就是获取注解信息的地⽅2. 注解获取以后便创建⾃定义的时间解析器猜想,我们可不可以也实现这个类,重写⽣成解析器的⽅法?那就试试呗~我们在⾃定义的时间解析器上同样实现这个类,重写了⽣成时间解析器的⽅法,并初始化⼀些⾃定义的信息供解析时间使⽤(当然猜想是正确的,因为官⽅就是这么搞的,只是官⽅的是⼀个内部类实现的),具体代码如下:时间解析器代码:import com.fasterxml.jackson.annotation.JsonFormat;import com.fasterxml.jackson.core.JsonParser;import com.fasterxml.jackson.databind.BeanProperty;import com.fasterxml.jackson.databind.DeserializationContext;import com.fasterxml.jackson.databind.JsonDeserializer;import com.fasterxml.jackson.databind.deser.ContextualDeserializer;import com.fasterxml.jackson.databind.util.StdDateFormat;import mon.collect.Lists;import ErrorCode;import Exception;import java.io.IOException;import java.text.DateFormat;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.List;import java.util.Locale;import java.util.TimeZone;import ng.StringUtils;import ng3.time.DateUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/*** @author ⽆名⼩⽣ Date: 2019-02-19 Time: 19:00* @version $Id$*/public class DateJsonDeserializer extends JsonDeserializer<Date> implements ContextualDeserializer {private final static Logger logger = LoggerFactory.getLogger(DateJsonDeserializer.class);private final static List<String> FORMATS = Lists.newArrayList("yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyyMMdd-HHmmss", "yyyy-MM-dd", "MM-dd", "HH:mm:ss", "yyyy-MM");public final DateFormat df;public final String formatString;public DateJsonDeserializer() {this.df = null;this.formatString = null;this.df = df;this.formatString = "";}public DateJsonDeserializer(DateFormat df, String formatString) {this.df = df;this.formatString = formatString;}@Overridepublic Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {try {String dateValue = p.getText();if (df == null || StringUtils.isEmpty(dateValue)) {return null;}("使⽤⾃定义解析器解析字段:{}:时间:{}",p.getCurrentName(),p.getText());Date date;if (StringUtils.isNumeric(dateValue)){date = new Date(Long.valueOf(dateValue));}else {String[] patterns = FORMATS.toArray(new String[0]);date = DateUtils.parseDate(p.getText(),patterns);}return df.parse(df.format(date));} catch (ParseException | SecurityException e) {logger.error("JSON反序列化,时间解析失败", e);throw new BizException(BizErrorCode.UNEXPECTED_ERROR);}}@Overridepublic JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) {if (property != null) {JsonFormat.Value format = ctxt.getAnnotationIntrospector().findFormat(property.getMember());if (format != null) {TimeZone tz = format.getTimeZone();// First: fully custom pattern?if (format.hasPattern()) {final String pattern = format.getPattern();if (!FORMATS.contains(pattern)){FORMATS.add(pattern);}final Locale loc = format.hasLocale() ? format.getLocale() : ctxt.getLocale();SimpleDateFormat df = new SimpleDateFormat(pattern, loc);if (tz == null) {tz = ctxt.getTimeZone();}df.setTimeZone(tz);return new DateJsonDeserializer(df, pattern);}// But if not, can still override timezoneif (tz != null) {DateFormat df = ctxt.getConfig().getDateFormat();// one shortcut: with our custom format, can simplify handling a bitif (df.getClass() == StdDateFormat.class) {final Locale loc = format.hasLocale() ? format.getLocale() : ctxt.getLocale();StdDateFormat std = (StdDateFormat) df;std = std.withTimeZone(tz);std = std.withLocale(loc);df = std;} else {// otherwise need to clone, re-set timezone:df = (DateFormat) df.clone();df.setTimeZone(tz);}return new DateJsonDeserializer(df);}}}return this;}}⾄此,⾃定义时间解析器就完成了但是,为了能够更灵活的控制时间的解析(例如:输⼊的时间格式和⽬标时间格式不同),我⼜重新⾃定义了⼀个时间解析的注解,基本仿照官⽅的@Format注解,具体代码如下⾃定义时间解析注解:import com.fasterxml.jackson.annotation.JacksonAnnotation;import ng.annotation.ElementType;import ng.annotation.Retention;import ng.annotation.RetentionPolicy;import ng.annotation.Target;import java.util.Locale;import java.util.TimeZone;/*** @author ⽆名⼩⽣ Date: 2019-02-21 Time: 11:03* @version $Id$*/@Target({ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER,ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@JacksonAnnotationpublic @interface DeserializeFormat {/*** Value that indicates that default {@link java.util.Locale}* (from deserialization or serialization context) should be used:* annotation does not define value to use.*/public final static String DEFAULT_LOCALE = "##default";/*** Value that indicates that default {@link java.util.TimeZone}* (from deserialization or serialization context) should be used:* annotation does not define value to use.*/public final static String DEFAULT_TIMEZONE = "##default";/*** 按照特定的时间格式解析*/public String pattern() default "";/*** ⽬标格式* @return*/public String format() default "";/*** Structure to use for serialization: definition of mapping depends on datatype,* but usually has straight-forward counterpart in data format (JSON).* Note that commonly only a subset of shapes is available; and if 'invalid' value* is chosen, defaults are usually used.*/public DeserializeFormat.Shape shape() default DeserializeFormat.Shape.ANY;* {@link java.util.Locale} to use for serialization (if needed).* Special value of {@link #DEFAULT_LOCALE}* can be used to mean "just use the default", where default is specified* by the serialization context, which in turn defaults to system* defaults ({@link java.util.Locale#getDefault()}) unless explicitly* set to another locale.*/public String locale() default DEFAULT_LOCALE;/*** {@link java.util.TimeZone} to use for serialization (if needed).* Special value of {@link #DEFAULT_TIMEZONE}* can be used to mean "just use the default", where default is specified* by the serialization context, which in turn defaults to system* defaults ({@link java.util.TimeZone#getDefault()}) unless explicitly* set to another locale.*/public String timezone() default DEFAULT_TIMEZONE;/*/**********************************************************/* Value enumeration(s), value class(es)/***********************************************************//*** Value enumeration used for indicating preferred Shape; translates* loosely to JSON types, with some extra values to indicate less precise* choices (i.e. allowing one of multiple actual shapes)*/public enum Shape{/*** Marker enum value that indicates "default" (or "whatever") choice; needed* since Annotations can not have null values for enums.*/ANY,/*** Value that indicates shape should not be structural (that is, not* {@link #ARRAY} or {@link #OBJECT}, but can be any other shape.*/SCALAR,/*** Value that indicates that (JSON) Array type should be used.*/ARRAY,/*** Value that indicates that (JSON) Object type should be used.*/OBJECT,/*** Value that indicates that a numeric (JSON) type should be used* (but does not specify whether integer or floating-point representation* should be used)*/NUMBER,/*** Value that indicates that floating-point numeric type should be used*/NUMBER_FLOAT,/*** Value that indicates that integer number type should be used* (and not {@link #NUMBER_FLOAT}).*/NUMBER_INT,/*** Value that indicates that (JSON) String type should be used.*/STRING,/*** Value that indicates that (JSON) boolean type* (true, false) should be used.*/BOOLEAN;public boolean isNumeric() {return (this == NUMBER) || (this == NUMBER_INT) || (this == NUMBER_FLOAT);}public boolean isStructured() {return (this == OBJECT) || (this == ARRAY);}}/*** Helper class used to contain information from a single {@link DeserializeFormat}* annotation.*/public static class Value{private final String pattern;private final String format;private final DeserializeFormat.Shape shape;private final Locale locale;private final String timezoneStr;// lazily constructed when created from annotationsprivate TimeZone _timezone;public Value() {this("", "", DeserializeFormat.Shape.ANY, "", "");}public Value(DeserializeFormat ann) {this(ann.pattern(),ann.format(), ann.shape(), ann.locale(), ann.timezone());}public Value(String p, String f, DeserializeFormat.Shape sh, String localeStr, String tzStr) {this(p,f, sh,(localeStr == null || localeStr.length() == 0 || DEFAULT_LOCALE.equals(localeStr)) ? null : new Locale(localeStr),(tzStr == null || tzStr.length() == 0 || DEFAULT_TIMEZONE.equals(tzStr)) ?null : tzStr,null);}/*** @since 2.1*/public Value(String p, String f, DeserializeFormat.Shape sh, Locale l, TimeZone tz){pattern = p;format = f;shape = (sh == null) ? DeserializeFormat.Shape.ANY : sh;locale = l;_timezone = tz;timezoneStr = null;}/*** @since 2.4public Value(String p, String f, DeserializeFormat.Shape sh, Locale l, String tzStr, TimeZone tz){pattern = p;format = f;shape = (sh == null) ? DeserializeFormat.Shape.ANY : sh;locale = l;_timezone = tz;timezoneStr = tzStr;}/*** @since 2.1*/public DeserializeFormat.Value withPattern(String p,String f) {return new DeserializeFormat.Value(p, f, shape, locale, timezoneStr, _timezone);}/*** @since 2.1*/public DeserializeFormat.Value withShape(DeserializeFormat.Shape s) {return new DeserializeFormat.Value(pattern, format, s, locale, timezoneStr, _timezone);}/*** @since 2.1*/public DeserializeFormat.Value withLocale(Locale l) {return new DeserializeFormat.Value(pattern, format, shape, l, timezoneStr, _timezone);}/*** @since 2.1*/public DeserializeFormat.Value withTimeZone(TimeZone tz) {return new DeserializeFormat.Value(pattern, format, shape, locale, null, tz);}public String getPattern() { return pattern; }public String getFormat() { return format; }public DeserializeFormat.Shape getShape() { return shape; }public Locale getLocale() { return locale; }/*** Alternate access (compared to {@link #getTimeZone()}) which is useful* when caller just wants time zone id to convert, but not as JDK* provided {@link TimeZone}** @since 2.4*/public String timeZoneAsString() {if (_timezone != null) {return _timezone.getID();}return timezoneStr;}public TimeZone getTimeZone() {TimeZone tz = _timezone;if (tz == null) {if (timezoneStr == null) {return null;}tz = TimeZone.getTimeZone(timezoneStr);_timezone = tz;}return tz;}/*** @since 2.4*/public boolean hasShape() { return shape != DeserializeFormat.Shape.ANY; }/*** @since 2.4*/public boolean hasPattern() {return (pattern != null) && (pattern.length() > 0);}/*** @since 2.4*/public boolean hasFormat() {return (format != null) && (format.length() > 0);}/*** @since 2.4*/public boolean hasLocale() { return locale != null; }/*** @since 2.4*/public boolean hasTimeZone() {return (_timezone != null) || (timezoneStr != null && !timezoneStr.isEmpty());}}}使⽤⾃定义解析注解的时间解析器import com.fasterxml.jackson.core.JsonParser;import com.fasterxml.jackson.databind.BeanProperty;import com.fasterxml.jackson.databind.DeserializationContext;import com.fasterxml.jackson.databind.JsonDeserializer;import com.fasterxml.jackson.databind.deser.ContextualDeserializer;import com.fasterxml.jackson.databind.util.StdDateFormat;import mon.collect.Lists;import ErrorCode;import Exception;import java.io.IOException;import java.text.DateFormat;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.List;import java.util.Locale;import java.util.TimeZone;import ng.StringUtils;import ng3.time.DateUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/*** @author ⽆名⼩⽣ Date: 2019-02-19 Time: 19:00* @version $Id$*/public class DateJsonDeserializer extends JsonDeserializer<Date> implements ContextualDeserializer {private final static Logger logger = LoggerFactory.getLogger(DateJsonDeserializer.class);private final static List<String> FORMATS = Lists.newArrayList("yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyyMMdd-HHmmss", "yyyy-MM-dd", "MM-dd", "HH:mm:ss",public final DateFormat df;public final String formatString;public DateJsonDeserializer() {this.df = null;this.formatString = null;}public DateJsonDeserializer(DateFormat df) {this.df = df;this.formatString = "";}public DateJsonDeserializer(DateFormat df, String formatString) {this.df = df;this.formatString = formatString;}@Overridepublic Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {try {String dateValue = p.getText();if (df == null || StringUtils.isEmpty(dateValue)) {return null;}Date date;if (StringUtils.isNumeric(dateValue)){date = new Date(Long.valueOf(dateValue));}else {String[] formatArray = FORMATS.toArray(new String[0]);date = DateUtils.parseDate(p.getText(),formatArray);}return df.parse(df.format(date));} catch (ParseException | SecurityException e) {logger.error("JSON反序列化,时间解析失败", e);throw new BizException(BizErrorCode.UNEXPECTED_ERROR);}}@Overridepublic JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) {if (property != null) {// JsonFormat.Value format = ctxt.getAnnotationIntrospector().findFormat(property.getMember());DeserializeFormat deFormat = property.getAnnotation(DeserializeFormat.class);DeserializeFormat.Value format = (deFormat == null) ? null : new DeserializeFormat.Value(deFormat); if (format != null) {TimeZone tz = format.getTimeZone();// First: fully custom pattern?if (format.hasPattern() && !FORMATS.contains(format.getPattern())){FORMATS.add(format.getPattern());}if (format.hasFormat()) {final String dateFormat = format.getFormat();final Locale loc = format.hasLocale() ? format.getLocale() : ctxt.getLocale();SimpleDateFormat df = new SimpleDateFormat(dateFormat, loc);if (tz == null) {tz = ctxt.getTimeZone();}df.setTimeZone(tz);return new DateJsonDeserializer(df, dateFormat);}// But if not, can still override timezoneif (tz != null) {DateFormat df = ctxt.getConfig().getDateFormat();// one shortcut: with our custom format, can simplify handling a bitif (df.getClass() == StdDateFormat.class) {final Locale loc = format.hasLocale() ? format.getLocale() : ctxt.getLocale();StdDateFormat std = (StdDateFormat) df;std = std.withTimeZone(tz);std = std.withLocale(loc);df = std;} else {// otherwise need to clone, re-set timezone:df = (DateFormat) df.clone();df.setTimeZone(tz);}return new DateJsonDeserializer(df);}}}return this;}}@JsonFormat的使⽤实体类字段中添加@JsonFormat注解(),返回 yyyy-MM-dd HH:mm:ss 时间格式@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")private Date joinedDate;pattern:⽇期格式timezone:时区以上为个⼈经验,希望能给⼤家⼀个参考,也希望⼤家多多⽀持。
jackson 反序列化枚举的问题在Jackson中反序列化枚举类型时,可能会遇到一些问题。
下面是一些可能的问题和解决方法:1. 反序列化枚举失败:这可能是因为Jackson无法识别输入的字符串与枚举类型之间的映射关系。
可以使用注解`@JsonCreator`和`@JsonValue`来指定自定义的映射规则。
```javapublic enum MyEnum {VALUE1("value1"),VALUE2("value2");private String value;MyEnum(String value) {this.value = value;}@JsonCreatorpublic static MyEnum fromValue(String value) {for (MyEnum e : MyEnum.values()) {if (e.value.equals(value)) {return e;}}throw new IllegalArgumentException("Invalid value: " + value);}@JsonValuepublic String toValue() {return value;}}```2. 反序列化空字符串失败:如果输入的字符串是空字符串,Jackson默认情况下会抛出异常。
可以使用`@JsonSetter`注解指定为空字符串时的默认值。
```javapublic enum MyEnum {VALUE1,VALUE2;@JsonSetterpublic void setValue(String value) {if (value != null && !value.isEmpty()) {throw new IllegalArgumentException("Invalid value: " + value);}}}```3. 反序列化大小写不敏感的枚举:默认情况下,Jackson会按照枚举定义的顺序进行匹配,这意味着枚举类型的字符串必须完全匹配大小写。
本文由我司收集整编,推荐下载,如有疑问,请与我司联系JsonConvert.SerializeObject到具有不可为空的DateTime属性的类?JsonConvert.SerializeObject到具有不可为空的DateTime属性的类?[英]JsonConvert.SerializeObject to class with non-nullable DateTime properties?背景 I have some JSON which is deserialized to a Class which has DateTime properties. 我有一些JSON被反序列化为具有DateTime属性的类。
Sometimes the corresponding elements of the JSON are null. 有时JSON的相应元素为null。
When you try to deserialize the JSON to the class an error is thrown because a plain old DateTime can’t accept a null. 当您尝试将JSON反序列化到类时,会抛出错误,因为普通的旧DateTime不能接受null。
Easy but removes functionality 简单但删除功能 So the easiest resolution is to make the accepting properties of the class a nullable DateTime (DateTime?) but if you do that there’s then a lot of DateTime methods you can no longer use on those properties. 因此,最简单的解决方案是使类的接受属性成为可以为空的DateTime (DateTime?),但是如果你这样做,那么你就不能再在这些属性上使用很多DateTime方法了。
Redis使⽤redis存储对象反序列化异常SerializationFailedExce。
案例使⽤Redis进⾏对象存储,在处理业务逻辑的时候,丛Redis获取对象发现反序列化失败,抛出如下异常:Caused by: org.springframework.data.redis.serializer.SerializationException: Cannot deserialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to deserialize payload. Is the byte array a result of correspon at org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.deserialize(JdkSerializationRedisSerializer.java:82)at org.springframework.data.redis.core.AbstractOperations.deserializeValue(AbstractOperations.java:318)at org.springframework.data.redis.core.AbstractOperations$ValueDeserializingRedisCallback.doInRedis(AbstractOperations.java:58)at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:207)at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:169)at org.springframework.data.redis.core.AbstractOperations.execute(AbstractOperations.java:91)at org.springframework.data.redis.core.DefaultValueOperations.get(DefaultValueOperations.java:43)at com.ppmoney.geedai.wechat.service.wechat.impl.GetAccessTokenServiceImpl.get(GetAccessTokenServiceImpl.java:37)at com.ppmoney.geedai.wechat.service.wechat.impl.CustomMsgServiceImpl.send(CustomMsgServiceImpl.java:32)... 82 common frames omittedCaused by: org.springframework.core.serializer.support.SerializationFailedException: Failed to deserialize payload. Is the byte array a result of corresponding serialization for DefaultDeserializer?; nested exception is java.io.InvalidClassException: weixin.popu at org.springframework.core.serializer.support.DeserializingConverter.convert(DeserializingConverter.java:78)at org.springframework.core.serializer.support.DeserializingConverter.convert(DeserializingConverter.java:36)at org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.deserialize(JdkSerializationRedisSerializer.java:80)... 90 common frames omittedCaused by: java.io.InvalidClassException: weixin.popular.bean.token.Token; local class incompatible: stream classdesc serialVersionUID = -584152862903853930, local class serialVersionUID = 8841433872811285796at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:616)at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1623)at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518)at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774)at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)at org.springframework.core.serializer.DefaultDeserializer.deserialize(DefaultDeserializer.java:70)at org.springframework.core.serializer.support.DeserializingConverter.convert(DeserializingConverter.java:73)... 92 common frames omitted解决⽅案经排查,原因是存放的对象忘了添加序列化号,导致存储的序列化编号和反序列化编号不⼀致,所以反序列化异常。
jackson反序列化时忽律不能转化的类型
在Jackson反序列化过程中,如果遇到无法转换的类型,会抛出异常。
以下是一些可能导致反序列化失败的情况:
1. 类型不匹配:如果JSON中的数据类型与Java对象中的字段类型不匹配,Jackson将无法进行转换。
例如,JSON中的字符串类型字段被映射到Java 对象中的整数类型字段,或者JSON中的数组被映射到Java对象中的集合等。
2. 缺少依赖项:如果Jackson无法找到必要的依赖项,例如某个类或库,
则无法进行反序列化。
确保您的项目中包含了所有必要的依赖项。
3. 配置错误:如果在Jackson的配置中存在错误,例如使用了错误的注解
或配置了错误的属性,则可能会导致反序列化失败。
检查并确保您的配置是正确的。
4. 特殊类型处理:对于一些特殊类型,如自定义类型、枚举类型等,如果Jackson无法找到适当的处理方式,可能会导致反序列化失败。
在这种情况下,您可能需要实现自定义的反序列化器来处理这些特殊类型。
总之,如果遇到Jackson反序列化时忽略不能转化的类型问题,应该检查您的JSON数据、Java对象和Jackson的配置,以确保它们之间的类型匹配
和依赖项的正确性。
Java:实体类不能序列化异常当修改实体类之后调⽤接⼝出现不能序列化的异常时,⼀定要检查实体之间的关系是否都是正确的.could not serialize; nested exception is org.hibernate.type.SerializationException: could not serialize原因// 学⽣字段@Column(name = "user")private User user;发送请求会出错 500 "could not serialize; nested exception is org.hibernate.type.SerializationException: could not serialize 序列化失败// 学⽣字段@JoinColumn(name = "user")private User user;发送请求会出错 500 "could not serialize; nested exception is org.hibernate.type.SerializationException: could not serialize 序列化失败// 学⽣字段@ManyToOneprivate User user;成功表中添加user_id字段 joinColumn 可以省略// 学⽣字段@ManyToOne@Column(name = "user")private User user;⽤Column启动报错结论,存在⼀对多多对⼀多对多关系时必须使⽤注解否则会序列化失败 joincolumn只是改变字段名。
FastJson踩坑:@JsonField在反序列化时失效的解决问题描述⼀个对象(某个字段为枚举类型,为了不采⽤默认的序列化过程,⽤@JSONField指定了序列化器和反序列器,过程见旧博⽂),将其放到JSONArray中再序列化JSONArray对象,⽤得到的JSON字符串再反序列化时,发现能够正常反序列化出JSONArray,⽽对JSONArray中的某个元素再反序列化成类对象时,出错。
⽰例同样⽤旧博⽂的⽰例做个简单测试。
基本对象类Article。
public class Article {private String title;private String content;@JSONField(serializeUsing = AuditStatusCodec.class, deserializeUsing = AuditStatusCodec.class)private AuditStatus status;public Article(){}public Article(String title, String content, AuditStatus status){this.title = title;this.content = content;this.status = status;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}public AuditStatus getStatus() {return status;}public void setStatus(AuditStatus status) {this.status = status;}@Overridepublic String toString() {return "Article{" +"title='" + title + '\'' +", content='" + content + '\'' +", status=" + status +'}';}@Overridepublic boolean equals(Object o) {if (this == o){return true;}if (o == null || getClass() != o.getClass()){return false;}Article article = (Article) o;return Objects.equals(title, article.title) &&Objects.equals(content, article.content) &&status == article.status;}@Overridepublic int hashCode() {return Objects.hash(title, content, status);}}枚举类型AuditStatus。
为啥你⽤@JsonFormat注解时,LocalDateTime会反序列化失败?写在前⾯最近,有个⼩伙伴问我:我在SpringBoot项⽬中,使⽤@JsonFormat注解标注LocalDateTime类型的字段时,LocalDateTime反序列化失败,这个我该怎么处理呢?别急,我们⼀起来解决这个问题。
⼩伙伴的疑问解答⼩伙伴的疑问我们可以使⽤SpringBoot依赖中的@JsonFormat注解,将前端通过json传上来的时间,通过@RequestBody⾃动绑定到Bean⾥的LocalDateTime成员上。
具体的绑定注解使⽤⽅法如下所⽰。
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", locale = "zh", timezone = "GMT+8")出现问题的版本我使⽤Spring Boot 2.0.0 时,直接在字段上加上@JsonFormat 注解就可以完成数据的绑定。
⽽在使⽤Spring Boot 1.5.8时,只在字段上加上@JsonFormat 注解,在数据绑定时⽆法将Date类型的数据⾃动转化为字符串类型的数据。
解决⽅法1.将SpringBoot版本升级为2.0.0及以上。
2.如果不升级SpringBoot版本,可以按照下⾯的⽅式解决问题。
不升级SpringBoot版本,添加Jackson对Java Time的⽀持后,就能解决这个问题。
在pom.xml中添加:<dependency><groupId>com.fasterxml.jackson.module</groupId><artifactId>jackson-module-parameter-names</artifactId></dependency><dependency><groupId>com.fasterxml.jackson.datatype</groupId><artifactId>jackson-datatype-jdk8</artifactId></dependency><dependency><groupId>com.fasterxml.jackson.datatype</groupId><artifactId>jackson-datatype-jsr310</artifactId></dependency>添加JavaConfig,⾃动扫描新添加的模块:import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import com.fasterxml.jackson.databind.ObjectMapper;@Configurationpublic class JacksonConfig {@Beanpublic ObjectMapper serializingObjectMapper() {ObjectMapper objectMapper = new ObjectMapper();objectMapper.findAndRegisterModules();return objectMapper;}}或者在application.properties添加如下配置:spring.jackson.serialization.write-dates-as-timestamps=false或者只注册JavaTimeModule,添加下⾯的Bean@Beanpublic ObjectMapper serializingObjectMapper() {ObjectMapper objectMapper = new ObjectMapper();objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);objectMapper.registerModule(new JavaTimeModule());return objectMapper;}重磅福利微信搜⼀搜【冰河技术】微信公众号,关注这个有深度的程序员,每天阅读超硬核技术⼲货,公众号内回复【PDF】有我准备的⼀线⼤⼚⾯试资料和我原创的超硬核PDF技术⽂档,以及我为⼤家精⼼准备的多套简历模板(不断更新中),希望⼤家都能找到⼼仪的⼯作,学习是⼀条时⽽郁郁寡欢,时⽽开怀⼤笑的路,加油。
序列化根级别上的数据⽆效。
⾏1,位置1最近在做反序列化的时候遇到过根级别上的数据⽆效。
⾏ 1,位置 1最后发现是在序列化的时候代码不标准所致序列化代码:'''<summary>'''将Pack⽂件保存到本地⽂件,并返回⽂件名'''</summary>'''<param name="pk">List(Of PackageData)</param>'''<param name="fileName">fileName</param>'''<returns></returns>'''<remarks></remarks>Public Shared Function SavePackToFile(ByVal pk As List(Of PackageData), Optional ByVal fileName As String = "") As StringTryIf fileName.Trim.Length <= 0Then fileName = Guid.NewGuid().ToString + ".pak"Dim destFile As String = AppDomain.CurrentDomain.BaseDirectory + "\Download\" + fileNameDim ser As New DataContractSerializer(GetType(List(Of PackageData)))Dim wx As New Xml.XmlTextWriter(destFile, System.Text.Encoding.UTF8)ser.WriteObject(wx, pk)wx.Close()Catch ex As ExceptionThrow exEnd TryReturn fileNameEnd Function反序列化:'''<summary>'''反序列化PackageData'''</summary>'''<param name="s"></param>'''<returns></returns>'''<remarks></remarks>Public Shared Function Deserialize(ByVal s As String) As List(Of PackageData)TryDim txter As TextReader = New StringReader(s.Trim())Dim reader As New XmlTextReader(txter)Dim ser As New DataContractSerializer(GetType(List(Of PackageData)))Dim datas As List(Of PackageData) = CType(ser.ReadObject(reader), List(Of PackageData))reader.Close()txter.Close()Return datasCatch ex As ExceptionThrow exEnd TryReturn NothingEnd Function这样之后不会再报错了。
redis反序列化失败解决⽅案⼀、问题描述:执⾏代码:valueOperations.set(user1.getUserName() , user1);将对象存⼊redis,存⼊后变成了如下所⽰的样⼦。
⼆、原因分析我们⾸先在实体类中实现了序列化接⼝,这时,User对象序列化为了字节流,传输进⼊redis,但是在进⼊redis反序列化为key和value对象的时候发⽣了错误,因此这⾥出现此问题是因为redis的反序列化失败,这时我们就主要围绕redis反序列化失败进⾏研究。
三、解决⽅案这⾥对key和value分别进⾏反序列化,进⽽在redis中⽣成字符型的key和对象型value。
/*** @author yeyuting* @create 2021/2/19*/@Configurationpublic class RedisConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {RedisTemplate<String, Object> template = new RedisTemplate<>();RedisSerializer<String> redisSerializer = new StringRedisSerializer();template.setConnectionFactory(factory);//key序列化⽅式template.setKeySerializer(redisSerializer);//value序列化template.setValueSerializer(new JdkSerializationRedisSerializer());//value hashmap序列化template.setHashValueSerializer(redisSerializer);//key haspmap序列化template.setHashKeySerializer(redisSerializer);return template;}}执⾏后redis中是这样的:可知,key反序列话成功了,但是value对象反序列化失败了,接着就将注意⼒转移到value对象的反序列化中来。
hsf 反序列化不存在类
反序列化是计算机科学的关键概念,它的概念和定义有时候混淆,但是有C++,Java和其他一些语言使其可以使用。
它能够将数据结构和一些对象(比如一个数组或者类的实例)转换成字节序列的过程。
反序列化也有自己特殊的应用,比如文件传输、XML文档解析和序列化,但是最常见的情况就是用在网络编程中。
反序列化不存在类,因为反序列化不会产生类,只会从字节流中恢复出数据来,因此反序列化运行时是不创建类实例的,而只是将存储在可序列化对象中的某些数据恢复到相应的实例对象中。
反序列化就是反过来重新创建一个对象或数据结构,它从序列化的字节流中恢复出用来描述对象的原始信息,因此反序列化在允许在一个系统和另一个系统之间传输被序列化的状态时有用。
总的来说,反序列化提供了一种从字节流中恢复出数据结构或对象的方法,极富可能性,但它不需要创建类来实现,它只是提供一种从可序列化对象中恢复某些数据的方法,这样反序列化就完成了。
反序列化问题
反序列化问题是指在程序中对序列化的数据进行反序列化时可
能出现的一系列问题。
序列化是将对象转换为字节流的过程,而反序列化则是将字节流转换回对象的过程。
在反序列化过程中,可能会出现以下问题:
1. 安全问题:恶意攻击者可以通过序列化和反序列化来注入恶意代码,导致程序受到攻击。
2. 数据完整性问题:在序列化过程中,可能会丢失一些关键信息。
在反序列化时,这些信息并没有被还原,导致程序无法正确运行。
3. 版本兼容性问题:在序列化和反序列化过程中,如果涉及到不同版本的程序,则可能会出现兼容性问题,导致程序无法正常工作。
为了避免这些问题,开发人员应该采取一些措施来确保序列化和反序列化的安全性和兼容性。
例如,使用安全的序列化框架,对序列化数据进行完整性检查和验证,限制反序列化的权限,以及使用版本控制来检测程序的兼容性。
- 1 -。
对象逆序列化报错:ng.ClassNotFoundException 简单的想从保存的对象中⼜⼀次解析出对象。
⽤了逆序列化,但是报错:ng.ClassNotFoundException: xxxxxxxxxxxxat .URLClassLoader$1.run(URLClassLoader.java:366)at .URLClassLoader$1.run(URLClassLoader.java:355)at java.security.AccessController.doPrivileged(Native Method)at .URLClassLoader.findClass(URLClassLoader.java:354)at ng.ClassLoader.loadClass(ClassLoader.java:423)at uncher$AppClassLoader.loadClass(Launcher.java:308)at ng.ClassLoader.loadClass(ClassLoader.java:356)at ng.Class.forName0(Native Method)at ng.Class.forName(Class.java:264)at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:622)at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1593)at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1514)at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1750)at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)at java.io.ObjectInputStream.readObject(ObjectInputStream.java:369)at xxxxxxxxxxxxxxxxx(TestMetadata.java:103)提⽰类找不到。
json反序列化配置报错规则在软件开发过程中,经常会遇到需要将配置文件以json格式进行反序列化的情况。
然而,由于配置文件本身可能存在各种错误和不规范的情况,导致反序列化过程中出现错误。
本文将介绍一些常见的报错规则,帮助开发者更好地处理这些问题。
1. 语法错误当配置文件中存在语法错误时,json反序列化过程将会报错。
常见的语法错误包括缺少引号、括号不匹配、冒号和逗号的位置错误等。
为了解决这类问题,开发者需要仔细检查配置文件的语法是否正确,并确保所有的引号、括号、冒号和逗号都使用正确的格式。
2. 数据类型错误在json中,每个值都有对应的数据类型。
如果配置文件中的值与预期的数据类型不匹配,那么反序列化过程将会报错。
例如,如果配置文件中的某个值应该是一个整数,但实际上却是一个字符串,那么json反序列化器将无法将其解析为整数,从而报错。
为了避免这类问题,开发者需要确保配置文件中的值与预期的数据类型相匹配。
3. 缺少必要项有时候,配置文件中可能会缺少一些必要的项,导致反序列化过程中出现错误。
例如,配置文件中应该包含一个必须的参数,但实际上却没有提供。
为了解决这类问题,开发者需要仔细检查配置文件,确保所有必要的项都已经正确设置。
4. 重复的项配置文件中可能存在重复的项,导致反序列化过程中发生错误。
例如,配置文件中可能定义了两个相同名称的参数,这将导致反序列化器无法确定应该使用哪个值。
为了解决这类问题,开发者需要确保配置文件中的每个项都是唯一的,没有重复定义。
5. 无效的键名在json中,键名必须是字符串。
如果配置文件中的键名不是一个合法的字符串,那么反序列化过程将会报错。
为了避免这类问题,开发者需要确保配置文件中的键名都是合法的字符串,不包含特殊字符或空格。
6. 不支持的数据类型json支持的数据类型有限,如果配置文件中包含不支持的数据类型,那么反序列化过程将会报错。
例如,json不支持日期类型,如果配置文件中包含日期类型的值,那么反序列化过程将无法处理。
本文由我司收集整编,推荐下载,如有疑问,请与我司联系
反序列化无效的类
反序列化无效的类- 从文件工作反序列化但不是blob?[英]class invalid for deserialization - Deserializes from file working but not blob? The problem lies when trying to deserialize an instance of the class itemSet returned in a resultSet after querying my database. The blobfile seems to be fine itself and the data can be saved to a file then correctly read using a filereader (see below) as such I’m inclined to believe the issue lies somewhere in my implementation? The program runs on tomcat using the netbeans 8.01 ide.
问题在于在查询数据库后尝试反序列化在resultSet中返回的类itemSet的实例。
blobfile本身似乎很好,数据可以保存到文件然后使用文件读取器正确读取(见下文),因为我倾向于认为问题出在我的实现中的某个地方?该程序使用netbeans 8.01 ide在tomcat上运行。
My project git link: https://github/feltax/gw2apiMark2
我的项目git链接:https://github/feltax/gw2apiMark2
My project is using a modified wrapper for a few classes: https://github/feltax/gw2apiModified
我的项目使用一个修改过的包装器来完成几个
类:https://github/feltax/gw2apiModified
The exact error:
确切的错误:
type Exception report message me.nithanim.gw2api.v2.api.items.ItemInfo; class invalid for deserializationdescription The server encountered an internal error that prevented it from fulfilling this request.exception java.io.InvalidClassException: me.nithanim.gw2api.v2.api.items.ItemInfo; class invalid for deserialization java.io.ObjectStreamClass$ExceptionInfo.newInvalidClassException(ObjectStreamClass.j ava:150)java.io.ObjectStreamClass.checkDeserialize(ObjectStreamClass.java:790)java.io.。