Skip to content

Commit 760138b

Browse files
committed
refactor(framework): replace fastjson with jackson-databind
Replace all usages of fastjson with Jackson - Upgrades jackson-databind from 2.18.3 to 2.18.6 to address CVE GHSA-72hv-8253-57qq - Remove fastjson
1 parent 039821c commit 760138b

166 files changed

Lines changed: 4170 additions & 277 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ src/test/java/org/tron/consensus2
3636
src/main/java/META-INF/
3737
src/main/resources/META-INF/
3838
/bin/
39+
bin/
3940

4041
# Eclipse IDE specific files and folders
4142
/.project
@@ -57,3 +58,4 @@ Wallet
5758

5859
/framework/propPath
5960
.cache
61+
.claude

actuator/src/main/java/org/tron/core/vm/trace/ProgramTrace.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,12 +90,12 @@ public void merge(ProgramTrace programTrace) {
9090
this.ops.addAll(programTrace.ops);
9191
}
9292

93-
public String asJsonString(boolean formatted) {
94-
return serializeFieldsOnly(this, formatted);
93+
public String asJsonString() {
94+
return serializeFieldsOnly(this);
9595
}
9696

9797
@Override
9898
public String toString() {
99-
return asJsonString(true);
99+
return asJsonString();
100100
}
101101
}
Lines changed: 11 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,28 @@
11
package org.tron.core.vm.trace;
22

3-
import com.fasterxml.jackson.annotation.JsonAutoDetect;
4-
import com.fasterxml.jackson.core.JsonGenerator;
5-
import com.fasterxml.jackson.core.JsonProcessingException;
6-
import com.fasterxml.jackson.databind.JsonSerializer;
3+
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
4+
import com.fasterxml.jackson.annotation.PropertyAccessor;
75
import com.fasterxml.jackson.databind.ObjectMapper;
86
import com.fasterxml.jackson.databind.SerializationFeature;
9-
import com.fasterxml.jackson.databind.SerializerProvider;
10-
import com.fasterxml.jackson.databind.introspect.VisibilityChecker;
11-
import java.io.IOException;
7+
import com.fasterxml.jackson.databind.json.JsonMapper;
128
import lombok.extern.slf4j.Slf4j;
13-
import org.bouncycastle.util.encoders.Hex;
14-
import org.tron.common.runtime.vm.DataWord;
15-
import org.tron.core.vm.Op;
169

1710
@Slf4j(topic = "VM")
1811
public final class Serializers {
1912

20-
public static String serializeFieldsOnly(Object value, boolean pretty) {
21-
try {
22-
ObjectMapper mapper = createMapper(pretty);
23-
mapper.setVisibilityChecker(fieldsOnlyVisibilityChecker(mapper));
13+
private static final ObjectMapper mapper = JsonMapper.builder()
14+
.enable(SerializationFeature.INDENT_OUTPUT)
15+
.visibility(PropertyAccessor.FIELD, Visibility.ANY)
16+
.visibility(PropertyAccessor.GETTER, Visibility.NONE)
17+
.visibility(PropertyAccessor.IS_GETTER, Visibility.NONE)
18+
.build();
2419

20+
public static String serializeFieldsOnly(Object value) {
21+
try {
2522
return mapper.writeValueAsString(value);
2623
} catch (Exception e) {
2724
logger.error("JSON serialization error: ", e);
2825
return "{}";
2926
}
3027
}
31-
32-
private static VisibilityChecker<?> fieldsOnlyVisibilityChecker(ObjectMapper mapper) {
33-
return mapper.getSerializationConfig().getDefaultVisibilityChecker()
34-
.withFieldVisibility(JsonAutoDetect.Visibility.ANY)
35-
.withGetterVisibility(JsonAutoDetect.Visibility.NONE)
36-
.withIsGetterVisibility(JsonAutoDetect.Visibility.NONE);
37-
}
38-
39-
public static ObjectMapper createMapper(boolean pretty) {
40-
ObjectMapper mapper = new ObjectMapper();
41-
if (pretty) {
42-
mapper.enable(SerializationFeature.INDENT_OUTPUT);
43-
}
44-
return mapper;
45-
}
46-
47-
public static class DataWordSerializer extends JsonSerializer<DataWord> {
48-
49-
@Override
50-
public void serialize(DataWord energy, JsonGenerator jgen, SerializerProvider provider)
51-
throws IOException, JsonProcessingException {
52-
jgen.writeString(energy.value().toString());
53-
}
54-
}
55-
56-
public static class ByteArraySerializer extends JsonSerializer<byte[]> {
57-
58-
@Override
59-
public void serialize(byte[] memory, JsonGenerator jgen, SerializerProvider provider)
60-
throws IOException, JsonProcessingException {
61-
jgen.writeString(Hex.toHexString(memory));
62-
}
63-
}
64-
65-
public static class OpCodeSerializer extends JsonSerializer<Byte> {
66-
67-
@Override
68-
public void serialize(Byte op, JsonGenerator jgen, SerializerProvider provider)
69-
throws IOException, JsonProcessingException {
70-
jgen.writeString(Op.getNameOf(op));
71-
}
72-
}
7328
}

common/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ sourceCompatibility = 1.8
88

99

1010
dependencies {
11-
api group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.18.3' // https://github.com/FasterXML/jackson-databind/issues/3627
11+
api group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.18.6' // https://github.com/FasterXML/jackson-databind/issues/3627
1212
api "com.cedarsoftware:java-util:3.2.0"
1313
api group: 'org.apache.httpcomponents', name: 'httpasyncclient', version: '4.1.1'
1414
api group: 'commons-codec', name: 'commons-codec', version: '1.11'

common/src/main/java/org/tron/common/utils/JsonUtil.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
package org.tron.common.utils;
22

33
import com.fasterxml.jackson.databind.ObjectMapper;
4+
import com.fasterxml.jackson.databind.json.JsonMapper;
45
import org.springframework.util.StringUtils;
56

67
public class JsonUtil {
78

9+
private static final ObjectMapper om = JsonMapper.builder().build();
10+
811
public static final <T> T json2Obj(String jsonString, Class<T> clazz) {
912
if (!StringUtils.isEmpty(jsonString) && clazz != null) {
1013
try {
11-
ObjectMapper om = new ObjectMapper();
1214
return om.readValue(jsonString, clazz);
1315
} catch (Exception var3) {
1416
throw new RuntimeException(var3);
@@ -22,7 +24,6 @@ public static final String obj2Json(Object obj) {
2224
if (obj == null) {
2325
return null;
2426
} else {
25-
ObjectMapper om = new ObjectMapper();
2627
try {
2728
return om.writeValueAsString(obj);
2829
} catch (Exception var3) {
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
package org.tron.json;
2+
3+
import com.fasterxml.jackson.annotation.JsonInclude;
4+
import com.fasterxml.jackson.core.JsonParser;
5+
import com.fasterxml.jackson.core.JsonProcessingException;
6+
import com.fasterxml.jackson.databind.DeserializationFeature;
7+
import com.fasterxml.jackson.databind.JsonNode;
8+
import com.fasterxml.jackson.databind.MapperFeature;
9+
import com.fasterxml.jackson.databind.ObjectMapper;
10+
import com.fasterxml.jackson.databind.SerializationFeature;
11+
import com.fasterxml.jackson.databind.json.JsonMapper;
12+
import com.fasterxml.jackson.databind.node.ObjectNode;
13+
14+
/**
15+
* Drop-in replacement for {@code com.alibaba.fastjson.JSON}.
16+
* Swap the import line; no other source changes required for basic usages.
17+
*
18+
* <p>All static methods delegate to a shared, thread-safe Jackson {@link ObjectMapper} that is
19+
* configured to match the lenient parsing behavior historically provided by Fastjson:
20+
* <ul>
21+
* <li>Unquoted field names and single-quoted strings are accepted.</li>
22+
* <li>Unknown properties are ignored (Fastjson default).</li>
23+
* <li>Floating-point numbers are mapped to {@link java.math.BigDecimal} for precision.</li>
24+
* <li>Case-insensitive property matching is enabled.</li>
25+
* </ul>
26+
*/
27+
public final class JSON {
28+
29+
/**
30+
* Shared, fully-configured Jackson mapper. Exposed for callers that hold a mapper reference.
31+
*/
32+
public static final ObjectMapper MAPPER = JsonMapper.builder()
33+
.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true)
34+
.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true)
35+
.configure(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS, true)
36+
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
37+
.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
38+
.serializationInclusion(JsonInclude.Include.NON_NULL)
39+
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
40+
.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true)
41+
.build();
42+
43+
private JSON() {
44+
}
45+
46+
// -------------------------------------------------------------------------
47+
// parseObject
48+
// -------------------------------------------------------------------------
49+
50+
/**
51+
* Parses a JSON object string and returns a {@link JSONObject}.
52+
* Mirrors {@code JSON.parseObject(String)} and {@code JSONObject.parseObject(String)}.
53+
*/
54+
public static JSONObject parseObject(String text) {
55+
if (text == null || text.trim().isEmpty()) {
56+
return null;
57+
}
58+
try {
59+
return new JSONObject((ObjectNode) MAPPER.readTree(text));
60+
} catch (Exception e) {
61+
throw new JSONException("Failed to parse JSON object: " + e.getMessage(), e);
62+
}
63+
}
64+
65+
/**
66+
* Parses a JSON string and deserializes it into the given Java type.
67+
* Mirrors {@code JSON.parseObject(String, Class)}.
68+
*/
69+
public static <T> T parseObject(String text, Class<T> clazz) throws JsonProcessingException {
70+
if (text == null || text.isEmpty()) {
71+
return null;
72+
}
73+
return MAPPER.readValue(text, clazz);
74+
}
75+
76+
// -------------------------------------------------------------------------
77+
// parse (validate / generic parse — callers typically ignore the return value)
78+
// -------------------------------------------------------------------------
79+
80+
/**
81+
* Parses any valid JSON value. Throws {@link JSONException} on invalid input
82+
* so callers can detect malformed JSON (e.g. via try/catch), mirroring
83+
* Fastjson's observable behaviour in this codebase.
84+
* Mirrors {@code JSON.parse(String)}.
85+
*/
86+
public static JsonNode parse(String text) {
87+
if (text == null || text.isEmpty()) {
88+
return null;
89+
}
90+
try {
91+
return MAPPER.readTree(text);
92+
} catch (Exception e) {
93+
throw new JSONException("Failed to parse JSON: " + e.getMessage(), e);
94+
}
95+
}
96+
97+
/**
98+
* Parses a JSON array string and returns a {@link JSONArray}.
99+
* Mirrors {@code JSON.parseArray(String)} and {@code JSONArray.parseArray(String)}.
100+
*/
101+
public static JSONArray parseArray(String text) {
102+
return JSONArray.parseArray(text);
103+
}
104+
105+
// -------------------------------------------------------------------------
106+
// toJSONString
107+
// -------------------------------------------------------------------------
108+
109+
/**
110+
* Serializes an object to a compact JSON string.
111+
* Mirrors {@code JSON.toJSONString(Object)}.
112+
*/
113+
public static String toJSONString(Object obj) {
114+
if (obj == null) {
115+
return "null";
116+
}
117+
// Unwrap our own wrapper types so the inner Jackson node is serialized
118+
if (obj instanceof JSONObject) {
119+
return ((JSONObject) obj).unwrap().toString();
120+
}
121+
if (obj instanceof JSONArray) {
122+
return ((JSONArray) obj).unwrap().toString();
123+
}
124+
try {
125+
return MAPPER.writeValueAsString(obj);
126+
} catch (Exception e) {
127+
throw new JSONException("Failed to serialise object: " + e.getMessage(), e);
128+
}
129+
}
130+
131+
/**
132+
* Serializes an object to a JSON string, optionally pretty-printed.
133+
* Mirrors {@code JSON.toJSONString(Object, boolean)}.
134+
*/
135+
public static String toJSONString(Object obj, boolean prettyFormat) {
136+
if (!prettyFormat) {
137+
return toJSONString(obj);
138+
}
139+
if (obj == null) {
140+
return "null";
141+
}
142+
try {
143+
if (obj instanceof JSONObject) {
144+
return MAPPER.writerWithDefaultPrettyPrinter()
145+
.writeValueAsString(((JSONObject) obj).unwrap());
146+
}
147+
if (obj instanceof JSONArray) {
148+
return MAPPER.writerWithDefaultPrettyPrinter()
149+
.writeValueAsString(((JSONArray) obj).unwrap());
150+
}
151+
return MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
152+
} catch (Exception e) {
153+
throw new JSONException("Failed to serialise object: " + e.getMessage(), e);
154+
}
155+
}
156+
}

0 commit comments

Comments
 (0)