2012-05-07 4 views
6

전체 PHP 객체 그래프를 JSON 문자열 표현으로 직렬화하고 동일한 PHP 객체 그래프로 다시 직렬화하려고했습니다. 여기 PHP 객체 그래프를 JSON으로 serialize/unserialize

내가 생각 옵션을 요약 한 것입니다, 그들은 나를 위해 작동하지 않는 이유 :
  • serialize()

    내가하고 싶은 일을하지 않습니다, 그것은 PHP에 고유 한 형식을 사용하기 때문이다. 대부분의 언어에서 널리 지원되며 사람이 읽을 수있는/편집 할 수있는 형식을 원합니다.

  • json_encode()은 개체가 아닌 단순한 값과 배열을 사용하기 때문에 내가 원하는 것을하지 않습니다. (나는 실제로 내 구현이 사용하고, 아래를 참조하십시오.)

  • var_export()(내 현재 구현되지 않습니다 순환 참조를 처리하지 않고, 내가 원하는 것을하지 않는다 (위를 참조하십시오.) 댓글을보고이 문제의 설명은 아래 답변)

  • 세바스찬 버그만의 Object Freezer이 좋은 구현이지만, 내가하고 싶은 일을하거나하지 않습니다 - - 순환 참조 중 하나를 처리 할 수 ​​있습니다. 그것은 매우 긴 형태를 사용하고, 직렬화 된 객체를 GUID로 채우는 작업에 의존합니다.

  • Serialized 실제로 수행하지 않는 직렬화는 serialize()의 출력을 구문 분석하고 다른 표현을 생성합니다. XML이지만 해당 표현을 구문 분석 할 수 없습니다. (또한 JSON을 지원하지 않습니다 - XML은 매우 긴 형태이며, 내가 원하는 것이 아니다.)

내가 지금 공유 할 수있는 작업 구현이 있습니다

https://github.com/mindplay-dk/jsonfreeze

JSON- 순환 참조는 허용되지 않으며, 여러 연구 -

{ 
    "#type": "Order", 
    "orderNo": 123, 
    "lines": [{ 
     "#type": "OrderLine", 
     "item": "milk \"fuzz\"", 
     "amount": 3, 
     "options": null 
    }, { 
     "#type": "OrderLine", 
     "item": "cookies", 
     "amount": 7, 
     "options": { 
      "#type": "#hash", 
      "flavor": "chocolate", 
      "weight": "1\/2 lb" 
     } 
    }], 
    "paid": true 
} 

이러한 접근 방식은 순수 트리 구조 집계 작동하도록 설계되었습니다 : 객체 그래프의 표현은 다음과 같다 같은 대상에 대한 eference. 즉, 이것은 일반적인 목적이 아닙니다. serialize()unserialize() 어떤 PHP 개체 그래프에 대해 작동합니다.

initial approach에서 본질적으로 개체의 기본 0 목록 인 직렬화 된 양식을 사용했습니다. 목록의 첫 번째 객체 (숫자 0)는 직렬화 된 객체 그래프의 루트이며 다른 객체는 발견 된 순서대로 저장됩니다.

현재 구현에서 JSON 표현은 원래의 트리 구조와 유사하므로 JavaScript에서 객체 그래프의 JSON 표현으로 실제로 작업 할 수 있습니다. 유일한 편차는 array 유형 해시 (JSON 객체로 저장 됨)와 일반 array 유형 배열 (JSON으로 저장 됨)을 구별하는 데 사용되는 #hash "유형"이라는 마술 #type 속성 (속성 이름과의 충돌을 방지하기 위해 # 접두사가 붙음) 배열).


이전 기록에 대해서는이 기록을 남겨 두었습니다.

순환 참조는 각 객체의 직렬화 된 표현 안에 결코 중첩 된 객체를 저장하지 않고 처리됩니다. 대신 객체 참조는 object-index가있는 JSON 객체로 저장됩니다. {"__oref":2}은 object-list에 인덱스 2이있는 개체에 대한 참조입니다.

내 구현에서 배열 참조에 문제가 있습니다. 개체에 대한 참조를 배열로 복원하는 var_dump()가 채워지지만 일부 지점에서 배열이 복사되고 당신은 빈 사본으로 끝납니다. 나는 코드에서 도처에 & 문자를 배치하려했지만 참조로 전달하는 위치에 관계없이 최종 결과는 빈 배열입니다.

+0

문서화 된대로 PHP 독점 형식의 직렬화를 호출하지 않을 것입니다. [적어도 소스 코드 내부] (http://lxr.php.net/opengrok) /xref/PHP_TRUNK/ext/standard/var.c#php_var_serialize_intern) - 제 3 자도 마찬가지입니다. 그래서 당신은 그것을 사용할 수 있습니다. – hakre

+0

문서화 될지 모르지만 PHP는 unserialize() 구현이있는 유일한 플랫폼/언어입니다. 모든 주류 언어에서 이미 지원되는 JSON을 선호합니다. 또한 사람이 읽을 수 있습니다. –

+0

직렬화 된 데이터를 모든 곳에서 지원되는 XML로 변환 할 수 있습니다. [Serialized Library] (https://github.com/ktomk/Serialized)가이 작업을 수행합니다. json dumper btw로 확장하기가 어렵지 않아야합니다. - 그래서 어쩌면 당신은 그것을 유용하게 생각할 것입니다. – hakre

답변

2

완성 된 스크립트 (위의 게시는) 내 정확한 요구 사항을 충족

  • 직렬화 및 전체 집계를 unserialize.

  • 원본 데이터 구조와 매우 유사한 JSON 표현이 있어야합니다.

  • 동적으로 생성 된 키 또는 다른 데이터로 데이터 구조를 오염시키지 마십시오.

순환 참조를 처리하지 않습니다. comment above에서 지적했듯이 동일한 객체에 대한 순환 참조 또는 다중 참조를 모두 저장할 수있는 올바른 방법이 없습니다. 이것을 깨달았을 때, 나는 객체 그래프가 규칙적인 나무 여야한다고 결정했고,이 제한을 "좋은 것"으로 받아 들였다.

업데이트 : 출력은 들여 쓰기, 줄 바꿈 및 공백으로 서식을 지정할 수 있습니다. 제 목적을 위해 인간이 읽을 수있는 (그리고 소스 제어가 쉬운) 표현이 있어야합니다. (포맷은 필요에 따라 활성화 또는 비활성화 할 수 있습니다.)

0

이것이 사용자의 의도인지는 모르지만 개체의 공개 속성을 얻는 데 관심이있는 경우 get_object_vars ($ obj)가 트릭을 수행합니다.

<?php 

class foo { 
    public $fname = "John"; 
    public $sname = "Doe"; 
    private $status = null; 
    static $type = "person"; 


} 

$obj = new foo; 

print_r((get_object_vars($obj))); 

print json_encode(get_object_vars($obj)); 

?> 

출력 :

어레이 ([FNAME] => 존 [SNAME] => 미상)

{ "FNAME": "존", "SNAME": "미상"}

위의 방법은 함수 참조 및 전용 변수에 액세스하는 데 쓸모가 없지만이 코드를 사용하여 원하는 코드를 추가로 만들 수 있습니다.

Dinesh.

+0

내가 게시 한 구현물을 살펴 본다면, 그보다 훨씬 더 많은 것을 얻었습니다 ... –