Improved fault tolerance for json file deserialization (#595)

* 修复一个Gson发序列化json文件的空值问题

* Improved fault tolerance for json file deserialization
This commit is contained in:
cfuncode 2022-05-07 04:39:37 +08:00 committed by GitHub
parent ad84635540
commit 0152b146c5
2 changed files with 56 additions and 15 deletions

View File

@ -7,6 +7,7 @@ import java.util.Map.Entry;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import com.google.gson.Gson;
import emu.grasscutter.utils.Utils; import emu.grasscutter.utils.Utils;
import org.reflections.Reflections; import org.reflections.Reflections;
@ -120,16 +121,17 @@ public class ResourceLoader {
@SuppressWarnings({"rawtypes", "unchecked"}) @SuppressWarnings({"rawtypes", "unchecked"})
protected static void loadFromResource(Class<?> c, String fileName, Int2ObjectMap map) throws Exception { protected static void loadFromResource(Class<?> c, String fileName, Int2ObjectMap map) throws Exception {
try (FileReader fileReader = new FileReader(Grasscutter.getConfig().RESOURCE_FOLDER + "ExcelBinOutput/" + fileName)) { FileReader fileReader = new FileReader(Grasscutter.getConfig().RESOURCE_FOLDER + "ExcelBinOutput/" + fileName);
List list = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, c).getType()); Gson gson = Grasscutter.getGsonFactory();
List list = gson.fromJson(fileReader, List.class);
for (Object o : list) { for (Object o : list) {
GameResource res = (GameResource) o; Map<String, Object> tempMap = Utils.switchPropertiesUpperLowerCase((Map<String, Object>) o, c);
GameResource res = gson.fromJson(gson.toJson(tempMap), TypeToken.get(c).getType());
res.onLoad(); res.onLoad();
map.put(res.getId(), res); map.put(res.getId(), res);
} }
} }
}
private static void loadScenePoints() { private static void loadScenePoints() {
Pattern pattern = Pattern.compile("(?<=scene)(.*?)(?=_point.json)"); Pattern pattern = Pattern.compile("(?<=scene)(.*?)(?=_point.json)");

View File

@ -1,20 +1,24 @@
package emu.grasscutter.utils; package emu.grasscutter.utils;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.time.*;
import java.time.temporal.TemporalAdjusters;
import java.util.Random;
import emu.grasscutter.Config; import emu.grasscutter.Config;
import emu.grasscutter.Grasscutter; import emu.grasscutter.Grasscutter;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil; import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import org.slf4j.Logger; import org.slf4j.Logger;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.time.DayOfWeek;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.temporal.TemporalAdjusters;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
@SuppressWarnings({"UnusedReturnValue", "BooleanMethodIsAlwaysInverted"}) @SuppressWarnings({"UnusedReturnValue", "BooleanMethodIsAlwaysInverted"})
public final class Utils { public final class Utils {
public static final Random random = new Random(); public static final Random random = new Random();
@ -230,4 +234,39 @@ public final class Utils {
} }
return (int)zonedDateTime.toInstant().atZone(ZoneOffset.UTC).toEpochSecond(); return (int)zonedDateTime.toInstant().atZone(ZoneOffset.UTC).toEpochSecond();
} }
public static Map<String, Object> switchPropertiesUpperLowerCase(Map<String, Object> objMap, Class<?> cls) {
Map<String, Object> map = new HashMap<>(objMap.size());
for (String key : objMap.keySet()) {
try {
char c = key.charAt(0);
if (c >= 'a' && c <= 'z') {
try {
cls.getDeclaredField(key);
map.put(key, objMap.get(key));
} catch (NoSuchFieldException e) {
String s1 = String.valueOf(c).toUpperCase();
String after = key.length() > 1 ? s1 + key.substring(1) : s1;
cls.getDeclaredField(after);
map.put(after, objMap.get(key));
}
} else if (c >= 'A' && c <= 'Z') {
try {
cls.getDeclaredField(key);
map.put(key, objMap.get(key));
} catch (NoSuchFieldException e) {
String s1 = String.valueOf(c).toLowerCase();
String after = key.length() > 1 ? s1 + key.substring(1) : s1;
cls.getDeclaredField(after);
map.put(after, objMap.get(key));
}
}
} catch (NoSuchFieldException e) {
map.put(key, objMap.get(key));
}
}
return map;
}
} }