Skip to content

Commit af2c452

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 af2c452

165 files changed

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

0 commit comments

Comments
 (0)