Skip to content

Commit

Permalink
fix reference detection does not work well when deserializing to JSON…
Browse files Browse the repository at this point in the history
…Object ,for issue #2180
  • Loading branch information
rowstop authored and wenshao committed Jan 15, 2024
1 parent 39ee760 commit c10c354
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 4 deletions.
19 changes: 19 additions & 0 deletions core/src/main/java/com/alibaba/fastjson2/JSONReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -2127,6 +2127,25 @@ public void read(Map object, long features) {
}
}

if (isReference()) {
String reference = readReference();
Object value = null;
if ("..".equals(reference)) {
value = map;
} else {
JSONPath jsonPath;
try {
jsonPath = JSONPath.of(reference);
} catch (Exception ignored) {
map.put(name, new JSONObject().fluentPut("$ref", reference));
continue;
}
addResolveTask(map, name, jsonPath);
}
map.put(name, value);
continue;
}

comma = false;
Object value;
switch (ch) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.alibaba.fastjson2.issues_2100;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONWriter;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

/**
* @author 张治保
* @since 2024/1/13
*/
public class Issue2180 {
@Getter
@Setter
@ToString
@EqualsAndHashCode
@Accessors(chain = true)
public static class Balance {
private Double amount;
private String currency;
}

@Getter
@Setter
@EqualsAndHashCode
@ToString
@Accessors(chain = true)
public static class Recovery {
private String name;
private Balance balance;
private Balance balance2;
private Balance recovery;
}

@Test
public void refTest() {
Balance usd = new Balance()
.setAmount(100.12)
.setCurrency("USD");
Recovery recovery = new Recovery()
.setName("hello")
.setBalance(usd)
.setBalance2(usd)
.setRecovery(usd);
String jsonString = JSON.toJSONString(recovery, JSONWriter.Feature.ReferenceDetection);
//完全相等 (在 JSONObject 中是完全相等的两个对象)
JSONObject jsonObject = JSON.parseObject(jsonString);
assertSame(jsonObject.get("balance"), jsonObject.get("balance2"));
assertSame(jsonObject.get("balance"), jsonObject.get("recovery"));
//原数据转成 jsonObject 然后转为对应类型 这里不完全相等,
//todo 使用JSONObject 转换之后不完全相等(不是同一个对象) 可优化
Recovery recovery2 = jsonObject.to(Recovery.class);
assertEquals(recovery2, recovery);
//原数据转换 完全相等
Recovery recovery3 = JSON.parseObject(jsonString, Recovery.class);
assertEquals(recovery3, recovery);
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package com.alibaba.fastjson2.v1issues.issue_3900;

import com.alibaba.fastjson2.JSONObject;
import org.json.JSONException;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;
import org.skyscreamer.jsonassert.JSONAssert;

public class Issue3922 {
@Test
public void test_for_issue3922() {
public void test_for_issue3922() throws JSONException {
String jsonString = "{\"this0\":{\"$ref\":\"1\"}}";
JSONObject jsonObject = JSONObject.parseObject(jsonString, JSONObject.class);
JSONObject innerObject = (JSONObject) jsonObject.get("this0");
assertEquals("{\"$ref\":\"1\"}", innerObject.toString());
JSONAssert.assertEquals("{\"$ref\":\"1\"}", innerObject.toString(), true);
}
}

0 comments on commit c10c354

Please sign in to comment.