JSON 도구 학습 기록 -- FastJSON 순환 참조 문제
16992 단어 JSONjavaWEB 실전
태그 (공백 구분): fastjson
최근 에 다른 사람의 프로젝트 를 바탕 으로 2 차 개발 을 하 다가 순환 인용 문제 에 부 딪 혔 다. 쉽게 말 하면 A 는 B, B 는 C, C 는 A 를 인용 했다. 그러면 제 이 슨 을 바 꾸 면 끊임없이 전환 된다. 더욱 복잡 한 상황 에서 A 는 B, B 에서 A 의 집합 을 인용 했다. 예 를 들 어 광고 유형 을 인용 했다 고 광고 유형 에 해당 유형의 소속 광고 가 있다.
1. 상황 구성
이런 것 을 쌍방 향 인용 이 라 고도 하 는데 개인 적 으로 이런 디자인 자체 가 합 리 적 이지 않다 고 생각 하기 때문에 당연히 구체 적 인 사용 장면 을 봐 야 한다.
광고 종류:
/**
* @author Niu Li
* @date 2016/8/12
*/
public class ADEntity {
private int id;
private String name;
//
private ADTypeEntity adTypeEntity;
public ADEntity(int id, String name, ADTypeEntity adTypeEntity) {
this.id = id;
this.name = name;
this.adTypeEntity = adTypeEntity;
}
// get set
}
광고 실체 클래스:
import java.util.List;
/**
* @author Niu Li
* @date 2016/8/12
*/
public class ADTypeEntity {
private int id;
private String name;
//
private List lists;
// get set
}
테스트 코드:
public class TestApp {
public static void main(String[] args) {
//
ADTypeEntity adTypeEntity = new ADTypeEntity();
adTypeEntity.setId(1);
adTypeEntity.setName(" ");
//
ADEntity entity1 = new ADEntity(1," 1",adTypeEntity);
ADEntity entity2 = new ADEntity(2," 2",adTypeEntity);
ADEntity entity3 = new ADEntity(3," 3",adTypeEntity);
List lists = new ArrayList();
lists.add(entity1);
lists.add(entity2);
lists.add(entity3);
//
adTypeEntity.setLists(lists);
String result = JSON.toJSONString(entity1);
System.out.println(result);
}
}
결 과 는 양 방향 인용 이 4. 567914 로 바 뀌 었 음 을 볼 수 있다.
{
"adTypeEntity": {
"id": 1,
"lists": [
{
"$ref": "$"
},
{
"adTypeEntity": {
"$ref": "$.adTypeEntity"
},
"id": 2,
"name": " 2"
},
{
"adTypeEntity": {
"$ref": "$.adTypeEntity"
},
"id": 3,
"name": " 3"
}
],
"name": " "
},
"id": 1,
"name": " 1"
}
2. 해결 방법
두 가지 해결 방법 은 순환 인용 이 있 는 곳 에 이 필드 를 걸 러 내 는 것 이다.
1. 필터 방식 은 JSONfield 주석 을 사용 하여 이 필드 가 json 으로 변환 되 지 않 음 을 설명 할 수 있 습 니 다.
@JSONField(serialize = false)
private List lists;
결 과 를 얻다
{
"adTypeEntity": {
"id": 1,
"name": " "
},
"id": 1,
"name": " 1"
}
2. 사용자 정의 변환 필드
SimplePropertyPreFilter filter = new SimplePropertyPreFilter(ADTypeEntity.class,"id","name");
String result = JSON.toJSONString(entity1,filter);
이것 은 ADTypeEntity 클래스 에 대해 id 와 name 필드 만 직렬 화 한 다 는 것 을 나타 낸다. 그러면 list 집합 인용 을 제외 하고 얻 은 결 과 는 위 와 같다.
3. 정상 변환 규칙 다단 계 필터
다음으로 전송:http://www.cnblogs.com/sandyfog/articles/3679804.html
fastjson 은 일부 인터페이스 에서 지정 한 필터 속성 을 실현 할 수 있 습 니 다. 필터 의 본질은 fastjson 이 매번 직렬 화 필드 를 할 때마다 Apply 방법 을 통 해 판단 합 니 다. Apply 가 true 로 돌아 갈 때 만 직렬 화 되 기 때문에 속성 명 에 따라 자 유 롭 게 걸 러 낼 수 있 습 니 다.
다음은 Property PreFilter 인 터 페 이 스 를 실현 하고 name 값 에 따라 판정 을 배제 합 니 다.
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.PropertyPreFilter;
import com.alibaba.fastjson.serializer.SerializerFeature;
import java.util.HashMap;
import java.util.Map;
/**
* @date 2016/8/17
*/
public class ComplexPropertyPreFilter implements PropertyPreFilter {
private Map, String[]> includes = new HashMap<>();
private Map, String[]> excludes = new HashMap<>();
static {
//
JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.DisableCircularReferenceDetect.getMask();
}
public ComplexPropertyPreFilter() {
}
public ComplexPropertyPreFilter(Map, String[]> includes) {
super();
this.includes = includes;
}
public boolean apply(JSONSerializer serializer, Object source, String name) {
// 。
if (source == null) {
return true;
}
//
Class> clazz = source.getClass();
// 、 ,
//
for (Map.Entry, String[]> item : this.excludes.entrySet()) {
// isAssignableFrom(),
if (item.getKey().isAssignableFrom(clazz)) {
String[] strs = item.getValue();
// name
if (isHave(strs, name)) {
return false;
}
}
}
//
if (this.includes.isEmpty()) {
return true;
}
//
//
for (Map.Entry, String[]> item : this.includes.entrySet()) {
// isAssignableFrom(),
if (item.getKey().isAssignableFrom(clazz)) {
String[] strs = item.getValue();
// name
if (isHave(strs, name)) {
return true;
}
}
}
return false;
}
/*
* , ,
*/
public static boolean isHave(String[] strs, String s) {
for (int i = 0; i < strs.length; i++) {
//
if (strs[i].equals(s)) {
// ,
return true;
}
}
// false
return false;
}
public Map, String[]> getIncludes() {
return includes;
}
public void setIncludes(Map, String[]> includes) {
this.includes = includes;
}
public Map, String[]> getExcludes() {
return excludes;
}
public void setExcludes(Map, String[]> excludes) {
this.excludes = excludes;
}
}
자기 코드 에 사용 되 는 필터
Pageable pageable = new Pageable(page,rows);
Page promotionPages = promotionService.findPage(pageable);
String[] promotionFilters = {"id", "name","title","image","endDate","priceExpression","memberRanks"};
String[] memberFilter = {"id","name"};
String[] pageFilter = {"pageNumber","pageSize","content","total","totalPages"};
Map,String[]> mapFilter = new HashMap<>();
mapFilter.put(Promotion.class,promotionFilters);
mapFilter.put(MemberRank.class,memberFilter);
mapFilter.put(Page.class,pageFilter);
ResultData result = new ResultData.Builder(ResultVo.OK)
.setData(APPJsonUtil.toJsonObject(mapFilter,null,promotionPages))
.builder();
json 도구
/**
* jsonObject,
* @param object
* @return
*/
public static JSONObject toJsonObject(Map, String[]> includes,Map, String[]> excludes, Object object){
ComplexPropertyPreFilter filter = new ComplexPropertyPreFilter();
if (excludes != null) {
filter.setExcludes(excludes);
}
if (includes != null) {
filter.setIncludes(includes);
}
String result = JSON.toJSONString(object, filter);
return JSON.parseObject(result);
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
스마트 폰 버전 Qiita에서 새로운 기사를 만드는 버튼을 모르기 때문에 QiitaAPI를 사용하여 어떻게 하는지 테스트오랜만에 신규 기사를 쓰려고 하면, 「작성 버튼…어디?」가 되어 전혀 발견되지 않았기 때문에, QiitaAPI와 Shortcuts로 어떻게든 한 이야기. 사용할 수 있는 도구는 스마트폰만(PC는 사용하지 않는다) S...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.