我只想将一些 JSON 保存并加载为字符串,源自
<LocalDate,Int>
的 HashMap
虽然我成功从 HashMap 生成 JSON 字符串,但我无法执行相反的操作,即从 JSON 字符串生成 HashMap。
这就是我转换为 Json 字符串的方法:
val gson = Gson()
val type = object:TypeToken<Map<LocalDate, Int>>(){}.type
val map: HashMap<LocalDate, Int> = HashMap()
val today = LocalDate.now()
map[today] = 1
val jsonStr = gson.toJson(map, type) // example of what this has: "{"2024-01-01":1}"
我也可以用它来看看确实应该可以解析字符串:
val jsonObject = JSONObject(jsonStr)
还要检查其中的值:
val countForToday = jsonObject.getInt(today.toString())
但是,当我使用这个时(查看这里之后):
var newMap: Map<LocalDate, Int> = gson.fromJson(jsonStr, object : TypeToken<Map<LocalDate, Int>>() {}.type)
我得到这个例外:
Method threw 'com.google.gson.JsonSyntaxException' exception.
IllegalStateException: Expected BEGIN_OBJECT but was STRING at line...
根据我从其他示例中看到的内容,我尝试过的所有方法都失败了:
GsonBuilder().create()
而不仅仅是Gson()
。我认为这并不重要,尽管 Gson()
可能是一个可以在任何地方使用的单例,甚至可能也是线程安全的。Map
代替HashMap,使用Any
代替Int
,使用?
(可为空)。我能想到的所有各种组合...现在我使用这个解决方法,不使用 Gson 转换回 HashMap:
val jsonObject = JSONObject(jsonStr)
val hashHap = HashMap<LocalDate, Int>()
jsonObject.keys().forEach { key: String ->
val date = LocalDate.parse(key)
val value = jsonObject.getInt(key)
hashHap[date] = value
}
这可行,但我想知道为什么 Gson 失败了。
发生什么事了?为什么我不能将这个简单的转换回 HashMap/Map(使用 Gson)?
您似乎在转换时遇到问题
LocalDate
。
您需要有一个自定义的日期序列化器和反序列化器。
它看起来会像这样:
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 java.lang.reflect.Type;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
/**
*
* @author asgar
*/
public class LocalDateConverter implements JsonSerializer<LocalDate>, JsonDeserializer<LocalDate> {
@Override
public JsonElement serialize(LocalDate src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(DateTimeFormatter.ISO_LOCAL_DATE.format(src));
}
@Override
public LocalDate deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
return DateTimeFormatter.ISO_LOCAL_DATE.parse(json.getAsString(), LocalDate::from);
}
}
之后就可以使用了。这是示例代码:
public static void main(String[] args) {
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(new TypeToken<LocalDate>() {}.getType(), new LocalDateConverter());
Gson gson1 = builder.create();
String jsonString = "{\"2023-01-01\":10,\"2023-02-15\":20,\"2023-05-08\":15,\"2023-08-20\":30}";
Type type = new TypeToken<HashMap<LocalDate, Integer>>() {
}.getType();
Map<LocalDate, Integer> map = gson1.fromJson(jsonString, type);
System.out.println("HashMap1: " + map);
}