Skip to content

Commit

Permalink
refactor: refactor functionalities around json serialization/deserial…
Browse files Browse the repository at this point in the history
…ization
  • Loading branch information
Zurcusa committed Aug 14, 2024
1 parent d1a854b commit 56a7132
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 32 deletions.
4 changes: 3 additions & 1 deletion src/main/java/com/limechain/chain/spec/ChainSpec.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.limechain.chain.spec;

import com.limechain.teavm.annotation.Reflectable;
import com.limechain.utils.json.JsonUtil;
import com.limechain.utils.json.ObjectMapper;
import lombok.Getter;
import lombok.Setter;
Expand Down Expand Up @@ -31,6 +32,7 @@ public class ChainSpec implements Serializable {
*/
public static ChainSpec newFromJSON(String pathToChainSpecJSON) throws IOException {
ObjectMapper mapper = new ObjectMapper(false);
return mapper.mapToClass(pathToChainSpecJSON, ChainSpec.class);
String jsonChainSpec = JsonUtil.readJsonFromFile(pathToChainSpecJSON);
return mapper.mapToClass(jsonChainSpec, ChainSpec.class);
}
}
10 changes: 3 additions & 7 deletions src/main/java/com/limechain/utils/json/JsonParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,7 @@ public JsonParser(String json) {
this.index = 0;
}

Map<String, Object> parse() {
return (Map<String, Object>) parseValue();
}

private Object parseValue() {
Object parse() {
skipWhitespace();
char currentChar = peek();
if (currentChar == '{') {
Expand Down Expand Up @@ -60,7 +56,7 @@ private Map<String, Object> parseObject() {
}
index++; // Skip ':'
skipWhitespace();
Object value = parseValue();
Object value = parse();
object.put(key, value);
skipWhitespace();
char currentChar = peek();
Expand All @@ -85,7 +81,7 @@ private List<Object> parseArray() {
}
while (true) {
skipWhitespace();
Object value = parseValue();
Object value = parse();
array.add(value);
skipWhitespace();
char currentChar = peek();
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/com/limechain/utils/json/JsonSerializer.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

public class JsonSerializer {

private final static DivLogger LOGGER = new DivLogger();
private static final DivLogger LOGGER = new DivLogger();

static String serializeToJson(Object object) {
StringBuilder jsonBuilder = new StringBuilder();
Expand Down Expand Up @@ -59,7 +59,7 @@ private static void appendObject(StringBuilder jsonBuilder, Object object) {
jsonBuilder.append(",");
}
} catch (IllegalAccessException e) {
LOGGER.log(Level.FINE, Arrays.toString(e.getStackTrace()));
LOGGER.log(Level.SEVERE, Arrays.toString(e.getStackTrace()));
}
}

Expand Down
10 changes: 4 additions & 6 deletions src/main/java/com/limechain/utils/json/JsonUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,17 @@

import com.limechain.teavm.HttpRequest;

import java.util.Map;

public class JsonUtil {

static Map<String, Object> parseJson(String jsonPath) {
return new JsonParser(readJsonFromFile(jsonPath)).parse();
static Object parseJson(String jsonString) {
return new JsonParser(jsonString).parse();
}

public String stringify(Object object) {
public static String stringify(Object object) {
return JsonSerializer.serializeToJson(object);
}

private static String readJsonFromFile(String filePath) {
public static String readJsonFromFile(String filePath) {
return HttpRequest.httpRequestSync("GET", filePath, null);
}
}
48 changes: 32 additions & 16 deletions src/main/java/com/limechain/utils/json/ObjectMapper.java
Original file line number Diff line number Diff line change
@@ -1,28 +1,35 @@
package com.limechain.utils.json;

import lombok.extern.java.Log;
import com.limechain.utils.DivLogger;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.Base64;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;

@Log
public class ObjectMapper {

private static final DivLogger LOGGER = new DivLogger();

private final boolean failOnUnknownField;

public ObjectMapper(boolean failOnUnknownField) {
this.failOnUnknownField = failOnUnknownField;
}

@SuppressWarnings("unchecked")
public <T> T mapToClass(String jsonString, Class<T> clazz) {
Map<String, Object> jsonMap = JsonUtil.parseJson(jsonString);
Object parsed = JsonUtil.parseJson(jsonString);

if (isPrimitiveOrWrapper(clazz) || clazz == String.class || clazz.isArray() || clazz == byte[].class) {
return convertValue(clazz, parsed);
}

try {
T instance = clazz.getDeclaredConstructor().newInstance();
for (Map.Entry<String, Object> entry : jsonMap.entrySet()) {
for (Map.Entry<String, Object> entry : ((Map<String, Object>) parsed).entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
Field field = findField(clazz, key);
Expand All @@ -44,46 +51,55 @@ private Field findField(Class<?> clazz, String fieldName) {
if (failOnUnknownField) {
throw new IllegalStateException("Field " + fieldName + " does not exist in " + clazz.getName());
} else {
log.fine("Field " + fieldName + " does not exist in " + clazz.getName());
LOGGER.log(Level.FINE, "Field " + fieldName + " does not exist in " + clazz.getName());
return null;
}
}
}

private static Object convertValue(Class<?> type, Object value) {
@SuppressWarnings("unchecked")
private <T> T convertValue(Class<T> type, Object value) {
if (value == null) {
return null;
}

if (type.isInstance(value)) {
return value;
return (T) value;
} else if (type == Integer.class || type == int.class) {
return ((Number) value).intValue();
return (T) (Integer) ((Number) value).intValue();
} else if (type == Double.class || type == double.class) {
return ((Number) value).doubleValue();
} else if (type == Boolean.class || type == boolean.class || type == byte.class) {
return value;
return (T) (Double) ((Number) value).doubleValue();
} else if (type == Boolean.class || type == boolean.class) {
return (T) value;
} else if (type == String.class) {
return value.toString();
return (T) value.toString();
} else if (type == byte[].class) {
if (value instanceof String) {
return Base64.getDecoder().decode((String) value);
return (T) Base64.getDecoder().decode((String) value);
} else {
throw new RuntimeException("Unsupported value type for byte[]: " + value.getClass());
}
} else if (type.isArray()) {
return convertArray(type.getComponentType(), (List<?>) value);
return (T) convertArray(type.getComponentType(), (List<?>) value);
}

// Add more type conversions as needed
throw new RuntimeException("Unsupported field type: " + type);
}

private static Object convertArray(Class<?> componentType, List<?> jsonArray) {
private Object convertArray(Class<?> componentType, List<?> jsonArray) {
Object array = Array.newInstance(componentType, jsonArray.size());
for (int i = 0; i < jsonArray.size(); i++) {
Array.set(array, i, convertValue(componentType, jsonArray.get(i)));
}
return array;
}

// Utility method to check if a class is a primitive type or its wrapper
private boolean isPrimitiveOrWrapper(Class<?> clazz) {
return clazz.isPrimitive() ||
clazz == Integer.class || clazz == Long.class ||
clazz == Double.class || clazz == Float.class ||
clazz == Boolean.class || clazz == Byte.class ||
clazz == Short.class || clazz == Character.class;
}
}

0 comments on commit 56a7132

Please sign in to comment.