当前位置:   article > 正文

使用Gson将对象json字符串转化成对象遇到的问题_gson json转换成一个不存在的对象

gson json转换成一个不存在的对象

场景一:存在一个对象User的json字符串,json字符串中存在对象类型为Integer或Double的属性值为空字符串,使用Gson将字符串转换为对象时报错,报错信息如下:

Exception in thread "main" com.google.gson.JsonSyntaxException: java.lang.NumberFormatException: empty String
	at com.google.gson.internal.bind.TypeAdapters$7.read(TypeAdapters.java:241)
	at com.google.gson.internal.bind.TypeAdapters$7.read(TypeAdapters.java:231)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:93)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:172)
	at com.google.gson.Gson.fromJson(Gson.java:803)
	at com.google.gson.Gson.fromJson(Gson.java:768)
	at com.google.gson.Gson.fromJson(Gson.java:717)
	at com.google.gson.Gson.fromJson(Gson.java:689)
	at JsonMain.main(JsonMain.java:15)
Caused by: java.lang.NumberFormatException: empty String
	at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1842)
	at sun.misc.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
	at java.lang.Double.parseDouble(Double.java:538)
	at com.google.gson.stream.JsonReader.nextInt(JsonReader.java:1178)
	at com.google.gson.internal.bind.TypeAdapters$7.read(TypeAdapters.java:239)
	... 8 more

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

对象信息如下:

package com.gj.bean;

import java.io.Serializable;

public class User implements Serializable {

	private static final long serialVersionUID = 6941951312521096768L;
	/** 用户id */
	private Integer id;
	/** 用户名 */
	private String name;
	/** 年龄 */
	private Integer age;
	/** 体重 */
	private Double weight;

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

	public Double getWeight() {
		return weight;
	}

	public void setWeight(Double weight) {
		this.weight = weight;
	}

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50

使用代码如下:

import com.gj.bean.User;
import com.google.gson.Gson;

public class JsonMain {

	public static void main(String[] args) {

		String json = "{\"id\":1,\"name\":\"test1\",\"age\":\"\"}";

		User obj = new Gson().fromJson(json, User.class);

	}

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

原因:Gson转换时将空字符串设置到Integer或Double类型的属性上,导致类型不匹配报错
解决办法:针对不同的数值类型的场景,写对应场景的类型转换器,实现Gson的序列化和反序列化接口:JsonSerializer接口和JsonDeserializer,在反序列化接口方法中,判断json值是否为空字符串值,如果是,则返回null或对应类型的默认值
如下所示:
DoubleDefaultNullAdapter.java

package com.gj.config;

import java.lang.reflect.Type;

import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.gson.JsonSyntaxException;

/**
 * @Description 将json字符串中Double类型字段值为空字符串的转化为null
 * @Author gj
 * @Date 2019/7/15
 * @Version 1.0
 **/
public class DoubleDefaultNullAdapter implements JsonSerializer<Double>, JsonDeserializer<Double> {
	/**
	 * Gson invokes this call-back method during deserialization when it encounters
	 * a field of the specified type.
	 * <p>
	 * In the implementation of this call-back method, you should consider invoking
	 * {@link JsonDeserializationContext#deserialize(JsonElement, Type)} method to
	 * create objects for any non-trivial field of the returned object. However, you
	 * should never invoke it on the the same type passing {@code json} since that
	 * will cause an infinite loop (Gson will call your call-back method again).
	 *
	 * @param json
	 *            The Json data being deserialized
	 * @param typeOfT
	 *            The type of the Object to deserialize to
	 * @param context
	 * @return a deserialized object of the specified type typeOfT which is a
	 *         subclass of {@code T}
	 * @throws JsonParseException
	 *             if json is not in the expected format of {@code typeofT}
	 */
	public Double deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
			throws JsonParseException {
		try {
			if (json.getAsString().equals("")) {
				// 定义为double类型,如果后台返回"",则返回null
				return null;
			}
		} catch (Exception ignore) {
		}
		try {
			return json.getAsDouble();
		} catch (NumberFormatException e) {
			throw new JsonSyntaxException(e);
		}
	}

	/**
	 * Gson invokes this call-back method during serialization when it encounters a
	 * field of the specified type.
	 *
	 * <p>
	 * In the implementation of this call-back method, you should consider invoking
	 * {@link JsonSerializationContext#serialize(Object, Type)} method to create
	 * JsonElements for any non-trivial field of the {@code src} object. However,
	 * you should never invoke it on the {@code src} object itself since that will
	 * cause an infinite loop (Gson will call your call-back method again).
	 * </p>
	 *
	 * @param src
	 *            the object that needs to be converted to Json.
	 * @param typeOfSrc
	 *            the actual type (fully genericized version) of the source object.
	 * @param context
	 * @return a JsonElement corresponding to the specified object.
	 */
	public JsonElement serialize(Double src, Type typeOfSrc, JsonSerializationContext context) {
		return new JsonPrimitive(src);
	}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80

IntegerDefaultNullAdapter.java

package com.gj.config;

import java.lang.reflect.Type;

import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.gson.JsonSyntaxException;

/**
 * @Description 将json字符串中Integer类型字段值为空字符串的转化为null
 * @Author gj
 * @Date 2019/7/15
 * @Version 1.0
 **/
public class IntegerDefaultNullAdapter implements JsonSerializer<Integer>, JsonDeserializer<Integer> {
	/**
	 * Gson invokes this call-back method during deserialization when it encounters
	 * a field of the specified type.
	 * <p>
	 * In the implementation of this call-back method, you should consider invoking
	 * {@link JsonDeserializationContext#deserialize(JsonElement, Type)} method to
	 * create objects for any non-trivial field of the returned object. However, you
	 * should never invoke it on the the same type passing {@code json} since that
	 * will cause an infinite loop (Gson will call your call-back method again).
	 *
	 * @param json
	 *            The Json data being deserialized
	 * @param typeOfT
	 *            The type of the Object to deserialize to
	 * @param context
	 * @return a deserialized object of the specified type typeOfT which is a
	 *         subclass of {@code T}
	 * @throws JsonParseException
	 *             if json is not in the expected format of {@code typeofT}
	 */
	public Integer deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
			throws JsonParseException {
		try {
			if (json.getAsString().equals("")) {
				// 定义为Integer类型,如果后台返回"",则返回null
				return null;
			}
		} catch (Exception ignore) {
		}
		try {
			return json.getAsInt();
		} catch (NumberFormatException e) {
			throw new JsonSyntaxException(e);
		}
	}

	/**
	 * Gson invokes this call-back method during serialization when it encounters a
	 * field of the specified type.
	 *
	 * <p>
	 * In the implementation of this call-back method, you should consider invoking
	 * {@link JsonSerializationContext#serialize(Object, Type)} method to create
	 * JsonElements for any non-trivial field of the {@code src} object. However,
	 * you should never invoke it on the {@code src} object itself since that will
	 * cause an infinite loop (Gson will call your call-back method again).
	 * </p>
	 *
	 * @param src
	 *            the object that needs to be converted to Json.
	 * @param typeOfSrc
	 *            the actual type (fully genericized version) of the source object.
	 * @param context
	 * @return a JsonElement corresponding to the specified object.
	 */
	public JsonElement serialize(Integer src, Type typeOfSrc, JsonSerializationContext context) {
		return new JsonPrimitive(src);
	}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80

使用方式:

import com.gj.bean.User;
import com.gj.config.DoubleDefaultNullAdapter;
import com.gj.config.IntegerDefaultNullAdapter;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class JsonMain {

	public static void main(String[] args) {

		String json = "{\"id\":1,\"name\":\"test1\",\"age\":\"\"}";

		// User obj = new Gson().fromJson(json, User.class);
		Gson gson = new GsonBuilder().registerTypeAdapter(Integer.class, new IntegerDefaultNullAdapter())
				.registerTypeAdapter(Double.class, new DoubleDefaultNullAdapter()).create();
		User obj = gson.fromJson(json, User.class);
		System.out.println(gson.toJson(obj));

	}

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

结果:
在这里插入图片描述
场景二:如果对象中含有日期或时间等属性值,最好将类型定义为String,如果定义为Date类型,那么它在json字符串中可能存在值为空字符串,反序列化时,会转换失败,如下图所示:
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/246297
推荐阅读
相关标签
  

闽ICP备14008679号