JSon 데이터 의 중복 참조 / 반복 참조 ($ref)

9358 단어 수필
인용 부호
인용 하 다.
묘사 하 다.
"$ref":".."
상급
"$ref":"@"
현재 대상
"$ref":"$"
루트 개체
"$ref":"$.children.0"
경로 기반 참조, root. getChildren (). get (0) 에 해당 합 니 다.
1. 무엇이 JSon 의 중복 인용 과 순환 인용 입 니까?
  • 중복 인용: 한 대상 의 여러 속성 이 같은 대상 을 동시에 인용 하거나 한 집합 에 같은 대상 을 동시에 추가 합 니 다.

  • 아래 코드 에서 우 리 는 같은 대상 을 한 집합 에 두 번 추가 한 다음 에 FastJSon 을 사용 하여 집합 을 JSon 문자열 로 변환 합 니 다.저희 가 기대 한 결 과 는 아마... [{"name": "test"}, {"name": "test"} 를 얻 었 습 니 다. [{"name": "test"}, {"$ref": "$[0]"}]. 백 엔 드 언어 에 서 는 정상적으로 해석 할 수 있 지만 앞 뒤 데이터 의 상호작용 과 관련 될 때 전단 언어 는 정확하게 해석 할 수 없 으 며 중복 인용 을 취소 해 야 합 니 다. 변환 할 때 인용 검 사 를 닫 을 수 있 습 니 다.
    [{"name": "test"}, {"$ref": "$[0]"}: 현재 집합 한 두 번 째 요 소 는 첫 번 째 요소 와 같 음 을 나타 내 며 첫 번 째 요 소 를 참조 합 니 다.
    $ref: 현재 요 소 는 다른 요 소 를 참조 합 니 다 $[0]: 현재 집합 한 0 번 요소 참조
        //       
        @Test
        public void test1() {
            //     
            ArrayList ones = new ArrayList<>();
    
            //     
            One one = new One();
            one.setName("test");
    
            //             
            ones.add(one);
            ones.add(one);
    
            //   FastJson      Json   
            String json = JSON.toJSONString(ones);
            System.out.println(json); //   Json  :[{"name":"test"},{"$ref":"$[0]"}]
        }
    
    
        //       
        @Test
        public void test1() {
            //     
            ArrayList ones = new ArrayList<>();
    
            //     
            One one = new One();
            one.setName("test");
    
            //             
            ones.add(one);
            ones.add(one);
    
            //   FastJson      Json   
            String json = JSON.toJSONString(ones, SerializerFeature.DisableCircularReferenceDetect);
            System.out.println(json); //   Json  :[{"name":"test"},{"name":"test"}]
        }

     
  • 순환 인용: 여러 대상 / 집합 사이 에 상호 인용 이 존재 한다. 예 를 들 어 A 대상 은 B 대상 을 인용 하 는 동시에 B 대상 은 A 대상 을 인용한다.
  • 맵 1 을 변환 할 때 맵 1 이 맵 2 를 인용 하 는 것 을 발견 하고 맵 2 를 도입 하 였 는데 맵 2 가 맵 1 을 사용 하 는 것 을 발견 하 였 습 니 다....................................................................................................상호 호출 처리 (기본적으로 순환 참조 검 사 를 열 었 습 니 다. 순환 참조 가 있 으 면 참조 기 호 를 사용 하여 대체 합 니 다) 순환 참조 검 사 를 닫 으 면 FastJSon 은 참조 대상 대신 인용 기 호 를 사용 하지 않 습 니 다. 그러면 무한 순환 상호 참조 로 인해 java. lang. Stack Overflow Error (스 택 메모리 넘 침 오류) 가 발생 할 수 있 습 니 다.
    순환 인용 은 실제 개발 에서 사 용 될 수 있 습 니 다. 예 를 들 어 캐릭터 기반 접근 제어 에서 사용자, 역할, 권한 등 세 가지 간 의 다 중 대응 관계 와 관련 될 수 있 습 니 다. 이때 실체 류 를 사용 하여 세 가지 간 의 대응 관 계 를 구축 할 때 순환 인용 을 사용 합 니 다. 한 사용 자 는 여러 개의 역할 을 가 질 수 있 고 한 캐릭터 는 여러 사용자 에 게 둘러싸 일 수 있 습 니 다.한 캐릭터 도 여러 가지 권한 을 가 질 수 있 고 한 가지 권한 도 여러 캐릭터 에 의 해 가 질 수 있다.
        //         
        @Test
        public void test3() {
           Map map1 = new HashMap();
            map1.put("test1", "Map1    ");
            Map map2 = new HashMap();
            map2.put("test2", "Map2    ");
    
            //     
            map1.put("Map1  Map2", map2);
            map2.put("Map2  Map1", map1);
    
            //   FastJson   Json   
            String json = JSON.toJSONString(map1);
    
            // {"  map2":{"map2":"test2","  map1":{"$ref":".."}},"map1":"test1"}
            System.out.println(json); 
    
        }
        
        //       
        @Test
        public void test4() {
            Map map1 = new HashMap<>();
            map1.put("map1", "test1");
    
            Map map2 = new HashMap<>();
            map2.put("map2", "test2");
    
    
            //     
            map1.put("  map2", map2);
            map2.put("  map1", map1);
    
            // SerializerFeature:      ;DisableCircularReferenceDetect:        
            String json = JSON.toJSONString(map1,SerializerFeature.DisableCircularReferenceDetect);
            
            // java.lang.StackOverflowError
            System.out.println(json);
        }

     
    2. JSon 의 중복 인용 과 순환 인용 문 제 를 어떻게 해결 합 니까?
    데 이 터 를 제 이 슨 데이터 로 변환 할 때 는 반복 적 으로 인 용 된 검 측 을 닫 아 제 이 슨 데이터 의 인용 기 호 를 제거 하고 실제 대상 데 이 터 를 사용 하여 표시 할 수 있 습 니 다. 그러나 순환 적 인 인용 을 만 났 을 때 계속 인용 이 순환 에 들 어가 면 순서 가 무 너 져 스 택 메모리 가 넘 치 는 오류 가 발생 할 수 있 습 니 다.
    따라서 FastJSon 의 순환 참 조 는 일반적인 상황 에서 기본 적 인 열 림 검사 상 태 를 유지 해 야 하기 때 문 입 니 다. 순환 참조 와 관련 이 있 으 면 분리 해서 저장 합 니 다.
    다음은 캐릭터 기반 접근 제어 종 사용자 와 캐릭터 실체 류 간 의 대응 관 계 를 사용 하여 인용 문제 의 해결 (간단 한 대응 관계) 을 보 여 줍 니 다.
    //      
    public class User implements Serializable {
    
        private String username; //    
        private String password; //   
        private List roles; //     
    
    }
    
    
    //      
    public class Role implements Serializable {
    
        private String roleName; //     
        private List users; //        
    
    }
    
    
        @Test
        public void test() {
            //        
            Use user = new Use("jack", "123"); //     
            Role role = new Role("   "); //     
    
            //     
            List roles = new ArrayList<>(); //        
            roles.add(role);
            user.setRoles(roles);
    
            List users = new ArrayList<>(); //        
            users.add(user);
            role.setUsers(users);
    
            //    Json  
            String json = JSON.toJSONString(user); //           ,      
            // {"password":"123","roles":[{"roleName":"   ","users":[{"$ref":"$"}]}],"username":"jack"}
            System.out.println(json);
        }

    순환 인용 으로 인해 인용 기호 와 스 택 메모리 가 넘 치 는 문제 의 근본 원인 은 (User 와 Role 을 열 로) 입 니 다. user 대상 은 roles 집합 을 참조 하고 roles 집합 중의 role 대상 은 user 대상 을 참조 합 니 다. 변환 과정 은 다음 과 같 습 니 다.
    사용자 대상 을 먼저 변환 합 니 다. 그리고 roles 집합 을 전환 하여 roles 집합 중의 role 대상 을 전환 합 니 다. role 대상 이 user 대상 을 인 용 했 기 때문에 user 대상 을 다시 전환 합 니 다. 1 ~ 3 단계 반복. 위 에서 알 수 있 듯 이 문 제 는 세 번 째 인용 에 나타 나 며, 동시에 JSon 데이터 의 변환 은 대상 의 속성 에 따라 변 환 됩 니 다. 따라서 우 리 는 세 번 째 단계 에서 role 대상 을 전환 할 때 role 이 현상 에 대한 user 인용 을 무시 하면 현재 대상 에 대한 인용 과 순환 에 들 어가 지 않도록 하 는 인용 관 계 를 사용 할 수 있 습 니 다.
    대상 속성 을 무시 하고 JSon 데이터 변환 을 할 때 변환 하지 않 는 방법:
    1. @ JSONfield 주석 (정적)
  • 역할: fastJSon 이 제공 하 는 주해 로 실체 류 의 속성 을 JSon 으로 전환 하 는 설정 을 합 니 다.
  • serialize 속성: 이 속성 이 JSon 변환 을 진행 할 때 변환 할 지 여 부 를 표시 합 니 다. 기본 값 은 true 로 변환 하고 false 는 변환 을 무시 합 니 다.
  • 단점: 주 해 를 직접 사용 하여 실체 류 의 속성 을 수식 하고 소스 코드 에 직접 쓰 며 수요 가 변경 되면 실체 류 의 소스 코드 를 수정 해 야 한다 (실체 류 는 서로 다른 장면 에서 서로 다른 수요 가 있다).
  • 아래 코드 와 같이 @ JSONfield 주석 을 사용 하여 Role 대상 의 users 속성 을 수식 하고 serialize 속성 을 false 로 지정 합 니 다. 그리고 순환 검 사 를 시작 한 상태 에서 다시 전환 합 니 다. role 의 users 대상 으로 전환 할 때 users 대상 을 자동 으로 무시 하고 변환 하지 않 으 면 인용 문제 가 발생 하지 않 습 니 다.
    //      
    public class User implements Serializable {
    
        private String username; //    
        private String password; //   
        private List roles; //     
    
    }
    
    
    //      
    public class Role implements Serializable {
    
        private String roleName; //     
    
        @JSONField(serialize = false) //     ,     。
        private List users; //        
    
    }
    
    
        @Test
        public void test() {
            //        
            Use user = new Use("jack", "123"); //     
            Role role = new Role("   "); //     
    
            //     
            List roles = new ArrayList<>(); //        
            roles.add(role);
            user.setRoles(roles);
    
            List users = new ArrayList<>(); //        
            users.add(user);
            role.setUsers(users);
    
            //    Json  
            String json = JSON.toJSONString(user); // {"password":"123","roles":[{"roleName":"   "}],"username":"jack"}
            System.out.println(json);
        }

     
    2. 필 터 를 사용 하여 변환 할 속성 을 지정 합 니 다 (동적)
    필터 (Simple Property PreFilter) 를 정의 합 니 다. JSon 변환 이 필요 한 실체 클래스 의 이름 을 지정 합 니 다. 이렇게 하면 FastJSon 변환 대상 을 사용 할 때 필터 에서 지정 한 속성 만 변환 할 수 있 으 며 지정 한 자동 무시 가 없습니다.
    메모: 이 방식 은 동적 으로 변환 할 대상 속성 을 지정 하지만 서로 다른 속성 이름 이 같 을 수 없 도록 요구 합 니 다.
        @Test
        public void test() {
            //        
            Use user = new Use("jack", "123"); //     
            Role role = new Role("   "); //     
    
            //     
            List roles = new ArrayList<>(); //        
            roles.add(role);
            user.setRoles(roles);
    
            List users = new ArrayList<>(); //        
            users.add(user);
            role.setUsers(users);
    
             //      ,           。
            SimplePropertyPreFilter filter = new SimplePropertyPreFilter("username", "password", "roles", "roleName");
    
            //    Json  
            String json = JSON.toJSONString(user, filter);
            System.out.println(json); // {"password":"123","roles":[{"roleName":"   "}],"username":"jack"}
        }

    Simple Property PreFilter 의 구조 함수 의 매개 변 수 는 가 변 매개 변수 유형 으로 매개 변 수 를 직접 전달 할 수도 있 고 전환 해 야 할 속성 을 String [] 배열 에 저장 한 다음 에 배열 을 전달 할 수도 있 습 니 다.
     public SimplePropertyPreFilter(String... properties){
            this(null, properties);
    }

    좋은 웹페이지 즐겨찾기