Java 使用日期时间反序列化 JSON 到对象
Java Deserialize JSON with datetime to object
我有问题。我有以下 JSON:
[
{
"Id":"8",
"MasterAgentId":"0",
"LastAgentStrategyId":"16116488969159",
"BotState":"Active",
"Owner":"Andre",
"ExtraNotifiers":"",
"Exchange":"lava",
"DateTime":"2021-01-27 22:12:02",
"AgentStatus":"Enabled",
"ProtectiveOrdersEnabled":"yes",
"Sim_Progress":"100",
"Sim_DateTime":"2021-01-27 09:18:00",
"Sim_Coin":"BTC",
"Sim_Price":"31626.580000",
"Sim_Profit":"1216.04",
"Sim_Profit_Perc":"60.80",
"Sim_StartDateTime":"2019-01-01 00:00:00",
"LastAgentStrategyRun":"2020-12-19 17:40:30.531000"
}
]
如您所见,我在 JSON 中有 4 个日期时间:DateTime, Sim_DateTime, Sim_StartDateTime, LastAgentStrategyRun
现在我为此创建了一个 class,如下所示:
import java.time.LocalDateTime;
public class Agent {
private int Id;
private int MasterAgentId;
private long LastAgentStrategyId;
private AgentBotState BotState;
private String Owner;
private String ExtraNotifiers;
private AgentExchanges Exchange;
private LocalDateTime DateTime;
private AgentStatus AgentStatus;
private String ProtectiveOrdersEnabled;
private String Sim_Progress;
private String Sim_DateTime;
private String Sim_Coin;
private double Sim_Price;
private double Sim_Profit;
private double Sim_Profit_Perc;
private LocalDateTime Sim_StartDateTime;
private LocalDateTime LastAgentStrategyRun;
}
但是当我使用 GSON 反序列化 json 时:
Gson gson = new Gson();
Type listType = new TypeToken<ArrayList<Agent>>() {}.getType();
ArrayList<Agent> agentList = new Gson().fromJson(jsonResponse, listType);
我收到以下错误:
但是代码崩溃并出现以下错误:
Exception in thread "main" com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 157 path $[0].DateTime
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:200)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.read(ReflectiveTypeAdapterFactory.java:103)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:196)
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.company.Main.main(Main.java:34)
Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 157 path $[0].DateTime
at com.google.gson.stream.JsonReader.beginObject(JsonReader.java:387)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:189)
... 9 more
现在,当我从 json 中删除所有日期时间时,它会正确解析,只有几个奇怪的警告:
WARNING: An illegal reflective access operation has occurred WARNING:
Illegal reflective access by
com.google.gson.internal.bind.ReflectiveTypeAdapterFactory
(file:/C:/Users/Alexander/.m2/repository/com/google/code/gson/gson/2.3.1/gson-2.3.1.jar)
to field java.time.LocalDateTime.date WARNING: Please consider
reporting this to the maintainers of
com.google.gson.internal.bind.ReflectiveTypeAdapterFactory WARNING:
Use --illegal-access=warn to enable warnings of further illegal
reflective access operations WARNING: All illegal access operations
will be denied in a future release
如何将日期时间字符串解析为对象以及如何消除警告?
更新
使用以下代码后:
Gson gson = new GsonBuilder().registerTypeAdapter(LocalDateTime.class, (JsonDeserializer<LocalDateTime>) (json, type, jsonDeserializationContext) -> {
Instant instant = Instant.ofEpochMilli(json.getAsJsonPrimitive().getAsLong());
return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
}).create();
Type listType = new TypeToken<ArrayList<Agent>>() {}.getType();
ArrayList<Agent> agentList = gson.fromJson(jsonResponse, listType);
我现在收到这个错误:
Exception in thread "main" java.lang.NumberFormatException: For input string: "2021-01-27 22:56:01"
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:68)
at java.base/java.lang.Long.parseLong(Long.java:707)
at java.base/java.lang.Long.parseLong(Long.java:832)
at com.google.gson.JsonPrimitive.getAsLong(JsonPrimitive.java:238)
at com.company.Main.lambda$main[=17=](Main.java:35)
at com.google.gson.TreeTypeAdapter.read(TreeTypeAdapter.java:58)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.read(ReflectiveTypeAdapterFactory.java:103)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:196)
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.company.Main.main(Main.java:40)
您需要注册 LocalDateTime:e.g.replace Gson gson = new Gson();
参见下面的代码:
更新了使用日期格式化程序解析 LocalDateTime 的答案,而不是创建 Instant。此外,您的日期格式不一致,有些是 return 秒,有些是毫秒,因此我提供了两种格式替代方案。
请查看使用简化代理的示例代码class
String jsonResponse = "[\n" +
" {\n" +
" \"DateTime\":\"2021-01-27 09:18:00\",\n" +
" \"Sim_StartDateTime\":\"2019-01-01 00:00:00\",\n" +
" \"LastAgentStrategyRun\":\"2020-12-19 17:40:30.531000\"\n" +
" }\n" +
']';
Gson gson = new GsonBuilder().registerTypeAdapter(LocalDateTime.class, (JsonDeserializer<LocalDateTime>) (json, type, jsonDeserializationContext) -> {
try{
return LocalDateTime.parse(json.getAsJsonPrimitive().getAsString(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
} catch (DateTimeParseException e){
return LocalDateTime.parse(json.getAsJsonPrimitive().getAsString(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSS"));
}
}).create();
Type listType = new TypeToken<ArrayList<Agent>>() {}.getType();
ArrayList<Agent> agentList = gson.fromJson(jsonResponse, listType);
System.out.println(agentList);
和代理 class
public class Agent {
private LocalDateTime DateTime;
private LocalDateTime Sim_StartDateTime;
private LocalDateTime LastAgentStrategyRun;
public LocalDateTime getDateTime() {
return DateTime;
}
public void setDateTime(LocalDateTime dateTime) {
DateTime = dateTime;
}
public LocalDateTime getSim_StartDateTime() {
return Sim_StartDateTime;
}
public void setSim_StartDateTime(LocalDateTime sim_StartDateTime) {
Sim_StartDateTime = sim_StartDateTime;
}
public LocalDateTime getLastAgentStrategyRun() {
return LastAgentStrategyRun;
}
public void setLastAgentStrategyRun(LocalDateTime lastAgentStrategyRun) {
LastAgentStrategyRun = lastAgentStrategyRun;
}
@Override
public String toString() {
return "Agent{" +
"DateTime=" + DateTime +
", Sim_StartDateTime=" + Sim_StartDateTime +
", LastAgentStrategyRun=" + LastAgentStrategyRun +
'}';
}
}
和输出
[Agent{DateTime=2021-01-27T09:18, Sim_StartDateTime=2019-01-01T00:00, LastAgentStrategyRun=2020-12-19T17:40:30.531}]
您可以使用 GsonUtils。但要注意以下问题:您在该字段中有不同 date/time 格式。这是不正确的,因为要解析此文件,您必须使用所需模板设置 date/time 格式化程序。我在 LastAgentStrategyRun
字段中更改了阵型,这是一个示例:
String json = "[\n" +
" {\n" +
" \"Id\":\"8\",\n" +
" \"MasterAgentId\":\"0\",\n" +
" \"LastAgentStrategyId\":\"16116488969159\",\n" +
" \"BotState\":\"Active\",\n" +
" \"Owner\":\"Andre\",\n" +
" \"ExtraNotifiers\":\"\",\n" +
" \"Exchange\":\"lava\",\n" +
" \"DateTime\":\"2021-01-27 22:12:02\",\n" +
" \"AgentStatus\":\"Enabled\",\n" +
" \"ProtectiveOrdersEnabled\":\"yes\",\n" +
" \"Sim_Progress\":\"100\",\n" +
" \"Sim_DateTime\":\"2021-01-27 09:18:00\",\n" +
" \"Sim_Coin\":\"BTC\",\n" +
" \"Sim_Price\":\"31626.580000\",\n" +
" \"Sim_Profit\":\"1216.04\",\n" +
" \"Sim_Profit_Perc\":\"60.80\",\n" +
" \"Sim_StartDateTime\":\"2019-01-01 00:00:00\",\n" +
" \"LastAgentStrategyRun\":\"2020-12-19 17:40:30\"\n" +
" }\n" +
']';
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
GsonDecorator gson = GsonHelper.createGsonDecorator(new GsonBuilderDecorator().withDateTimeFormatter(formatter));
List<Agent> agent = gson.readList(json, Agent.class);
我有问题。我有以下 JSON:
[
{
"Id":"8",
"MasterAgentId":"0",
"LastAgentStrategyId":"16116488969159",
"BotState":"Active",
"Owner":"Andre",
"ExtraNotifiers":"",
"Exchange":"lava",
"DateTime":"2021-01-27 22:12:02",
"AgentStatus":"Enabled",
"ProtectiveOrdersEnabled":"yes",
"Sim_Progress":"100",
"Sim_DateTime":"2021-01-27 09:18:00",
"Sim_Coin":"BTC",
"Sim_Price":"31626.580000",
"Sim_Profit":"1216.04",
"Sim_Profit_Perc":"60.80",
"Sim_StartDateTime":"2019-01-01 00:00:00",
"LastAgentStrategyRun":"2020-12-19 17:40:30.531000"
}
]
如您所见,我在 JSON 中有 4 个日期时间:DateTime, Sim_DateTime, Sim_StartDateTime, LastAgentStrategyRun
现在我为此创建了一个 class,如下所示:
import java.time.LocalDateTime;
public class Agent {
private int Id;
private int MasterAgentId;
private long LastAgentStrategyId;
private AgentBotState BotState;
private String Owner;
private String ExtraNotifiers;
private AgentExchanges Exchange;
private LocalDateTime DateTime;
private AgentStatus AgentStatus;
private String ProtectiveOrdersEnabled;
private String Sim_Progress;
private String Sim_DateTime;
private String Sim_Coin;
private double Sim_Price;
private double Sim_Profit;
private double Sim_Profit_Perc;
private LocalDateTime Sim_StartDateTime;
private LocalDateTime LastAgentStrategyRun;
}
但是当我使用 GSON 反序列化 json 时:
Gson gson = new Gson();
Type listType = new TypeToken<ArrayList<Agent>>() {}.getType();
ArrayList<Agent> agentList = new Gson().fromJson(jsonResponse, listType);
我收到以下错误:
但是代码崩溃并出现以下错误:
Exception in thread "main" com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 157 path $[0].DateTime
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:200)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.read(ReflectiveTypeAdapterFactory.java:103)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:196)
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.company.Main.main(Main.java:34)
Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 157 path $[0].DateTime
at com.google.gson.stream.JsonReader.beginObject(JsonReader.java:387)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:189)
... 9 more
现在,当我从 json 中删除所有日期时间时,它会正确解析,只有几个奇怪的警告:
WARNING: An illegal reflective access operation has occurred WARNING: Illegal reflective access by com.google.gson.internal.bind.ReflectiveTypeAdapterFactory (file:/C:/Users/Alexander/.m2/repository/com/google/code/gson/gson/2.3.1/gson-2.3.1.jar) to field java.time.LocalDateTime.date WARNING: Please consider reporting this to the maintainers of com.google.gson.internal.bind.ReflectiveTypeAdapterFactory WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations WARNING: All illegal access operations will be denied in a future release
如何将日期时间字符串解析为对象以及如何消除警告?
更新
使用以下代码后:
Gson gson = new GsonBuilder().registerTypeAdapter(LocalDateTime.class, (JsonDeserializer<LocalDateTime>) (json, type, jsonDeserializationContext) -> {
Instant instant = Instant.ofEpochMilli(json.getAsJsonPrimitive().getAsLong());
return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
}).create();
Type listType = new TypeToken<ArrayList<Agent>>() {}.getType();
ArrayList<Agent> agentList = gson.fromJson(jsonResponse, listType);
我现在收到这个错误:
Exception in thread "main" java.lang.NumberFormatException: For input string: "2021-01-27 22:56:01"
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:68)
at java.base/java.lang.Long.parseLong(Long.java:707)
at java.base/java.lang.Long.parseLong(Long.java:832)
at com.google.gson.JsonPrimitive.getAsLong(JsonPrimitive.java:238)
at com.company.Main.lambda$main[=17=](Main.java:35)
at com.google.gson.TreeTypeAdapter.read(TreeTypeAdapter.java:58)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.read(ReflectiveTypeAdapterFactory.java:103)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:196)
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.company.Main.main(Main.java:40)
您需要注册 LocalDateTime:e.g.replace Gson gson = new Gson();
参见下面的代码:
更新了使用日期格式化程序解析 LocalDateTime 的答案,而不是创建 Instant。此外,您的日期格式不一致,有些是 return 秒,有些是毫秒,因此我提供了两种格式替代方案。
请查看使用简化代理的示例代码class
String jsonResponse = "[\n" +
" {\n" +
" \"DateTime\":\"2021-01-27 09:18:00\",\n" +
" \"Sim_StartDateTime\":\"2019-01-01 00:00:00\",\n" +
" \"LastAgentStrategyRun\":\"2020-12-19 17:40:30.531000\"\n" +
" }\n" +
']';
Gson gson = new GsonBuilder().registerTypeAdapter(LocalDateTime.class, (JsonDeserializer<LocalDateTime>) (json, type, jsonDeserializationContext) -> {
try{
return LocalDateTime.parse(json.getAsJsonPrimitive().getAsString(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
} catch (DateTimeParseException e){
return LocalDateTime.parse(json.getAsJsonPrimitive().getAsString(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSS"));
}
}).create();
Type listType = new TypeToken<ArrayList<Agent>>() {}.getType();
ArrayList<Agent> agentList = gson.fromJson(jsonResponse, listType);
System.out.println(agentList);
和代理 class
public class Agent {
private LocalDateTime DateTime;
private LocalDateTime Sim_StartDateTime;
private LocalDateTime LastAgentStrategyRun;
public LocalDateTime getDateTime() {
return DateTime;
}
public void setDateTime(LocalDateTime dateTime) {
DateTime = dateTime;
}
public LocalDateTime getSim_StartDateTime() {
return Sim_StartDateTime;
}
public void setSim_StartDateTime(LocalDateTime sim_StartDateTime) {
Sim_StartDateTime = sim_StartDateTime;
}
public LocalDateTime getLastAgentStrategyRun() {
return LastAgentStrategyRun;
}
public void setLastAgentStrategyRun(LocalDateTime lastAgentStrategyRun) {
LastAgentStrategyRun = lastAgentStrategyRun;
}
@Override
public String toString() {
return "Agent{" +
"DateTime=" + DateTime +
", Sim_StartDateTime=" + Sim_StartDateTime +
", LastAgentStrategyRun=" + LastAgentStrategyRun +
'}';
}
}
和输出
[Agent{DateTime=2021-01-27T09:18, Sim_StartDateTime=2019-01-01T00:00, LastAgentStrategyRun=2020-12-19T17:40:30.531}]
您可以使用 GsonUtils。但要注意以下问题:您在该字段中有不同 date/time 格式。这是不正确的,因为要解析此文件,您必须使用所需模板设置 date/time 格式化程序。我在 LastAgentStrategyRun
字段中更改了阵型,这是一个示例:
String json = "[\n" +
" {\n" +
" \"Id\":\"8\",\n" +
" \"MasterAgentId\":\"0\",\n" +
" \"LastAgentStrategyId\":\"16116488969159\",\n" +
" \"BotState\":\"Active\",\n" +
" \"Owner\":\"Andre\",\n" +
" \"ExtraNotifiers\":\"\",\n" +
" \"Exchange\":\"lava\",\n" +
" \"DateTime\":\"2021-01-27 22:12:02\",\n" +
" \"AgentStatus\":\"Enabled\",\n" +
" \"ProtectiveOrdersEnabled\":\"yes\",\n" +
" \"Sim_Progress\":\"100\",\n" +
" \"Sim_DateTime\":\"2021-01-27 09:18:00\",\n" +
" \"Sim_Coin\":\"BTC\",\n" +
" \"Sim_Price\":\"31626.580000\",\n" +
" \"Sim_Profit\":\"1216.04\",\n" +
" \"Sim_Profit_Perc\":\"60.80\",\n" +
" \"Sim_StartDateTime\":\"2019-01-01 00:00:00\",\n" +
" \"LastAgentStrategyRun\":\"2020-12-19 17:40:30\"\n" +
" }\n" +
']';
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
GsonDecorator gson = GsonHelper.createGsonDecorator(new GsonBuilderDecorator().withDateTimeFormatter(formatter));
List<Agent> agent = gson.readList(json, Agent.class);