10.8 Serialization

10.8 Serialization

haxe.Serializerhaxe.Unserializer 클래스를 사용해 많은 런타임 값을 직렬화/역직렬화할 수 있습니다. 둘 다 두 가지 사용법을 지원합니다:

  • 인스턴스를 만들고 serialize/unserialize 메서드를 계속 호출해 여러 값을 처리.
  • 정적 run 메서드를 호출해 단일 값을 직렬화/역직렬화.

다음 예는 첫 번째 사용법을 보여줍니다:

import haxe.Serializer;
import haxe.Unserializer;

class Main {
  static function main() {
    var serializer = new Serializer();
    serializer.serialize("foo");
    serializer.serialize(12);
    var s = serializer.toString();
    trace(s); // y3:fooi12

    var unserializer = new Unserializer(s);
    trace(unserializer.unserialize()); // foo
    trace(unserializer.unserialize()); // 12
  }
}

직렬화 결과(여기서는 지역 변수 s에 저장)는 String이며 원격으로든 자유롭게 전달할 수 있습니다. 그 형식은 직렬화 형식(Serialization format)에 설명되어 있습니다.

지원되는 값(Supported values)
직렬화 설정(Serialization configuration)

직렬화는 두 가지 방법으로 설정할 수 있습니다. 둘 다 정적 변수를 설정해 모든 haxe.Serializer 인스턴스에 영향을 줄 수 있고, 멤버 변수를 설정해 특정 인스턴스에만 영향을 줄 수 있습니다:

  • USE_CACHE, useCache: true면 반복되는 구조나 클래스/enum 인스턴스가 참조로 직렬화됩니다. 재귀 데이터에 대해 순환 루프를 피할 수 있지만 직렬화 시간이 길어집니다. 기본적으로 객체 캐싱은 비활성화됩니다. 그러나 문자열은 항상 캐시됩니다.
  • USE_ENUM_INDEX, useEnumIndex: true면 enum 생성자가 이름 대신 인덱스로 직렬화됩니다. 결과 문자열을 더 짧게 만들 수 있지만, 역직렬화 전에 enum 생성자가 타입에 삽입되면 깨집니다. 이 동작은 기본적으로 비활성화됩니다.
역직렬화 동작(Deserialization behavior)

직렬화 결과를 저장해 나중에 역직렬화에 사용한다면, 클래스와 enum 인스턴스로 작업할 때 호환성을 유지하도록 주의해야 합니다. 그러면 unserialization이 정확히 어떻게 구현되는지 이해하는 것이 중요합니다.

  • 타입은 역직렬화가 이루어지는 런타임에서 사용 가능해야 합니다. 죽은 코드 제거(dead code elimination)가 활성화되면 직렬화를 통해서만 사용되는 타입이 제거될 수 있습니다.
  • Unserializer에는 이름으로 클래스와 enum을 해석하는 데 사용되는 멤버 변수 resolver가 있습니다. Unserializer 생성 시 이는 Unserializer.DEFAULT_RESOLVER로 설정됩니다. 둘 다(기본값과 인스턴스 멤버) 커스텀 resolver로 설정할 수 있습니다.
  • 클래스는 resolver.resolveClass(name)으로 이름으로 해석됩니다. 그런 다음 Type.createEmptyInstance로 인스턴스가 생성되는데, 이는 클래스 생성자가 호출되지 않는다는 뜻입니다. 마지막으로 직렬화된 값에 따라 인스턴스 필드가 설정됩니다.
  • Enum은 resolver.resolveEnum(name)으로 이름으로 해석됩니다. 그런 다음 사용 가능한 직렬화 인자 값이 있으면 이를 사용해 Type.createEnum으로 enum 인스턴스가 생성됩니다. 생성자 인자가 직렬화 이후 변경되었다면 결과는 지정되지 않습니다.
커스텀 (역)직렬화(Custom (de)serialization)

클래스가 멤버 메서드 hxSerialize를 정의하면 직렬화기가 이 메서드를 호출해 클래스의 커스텀 직렬화를 허용합니다. 마찬가지로 클래스가 멤버 메서드 hxUnserialize를 정의하면 역직렬화기가 이를 호출합니다:

import haxe.Serializer;
import haxe.Unserializer;

class Main {
  var x:Int;
  var y:Int;

  static function main() {
    var s = Serializer.run(new Main(1, 2));
    var c:Main = Unserializer.run(s);
    trace(c.x); // 1
    trace(c.y); // -1
  }

  function new(x, y) {
    this.x = x;
    this.y = y;
  }

  @:keep
  function hxSerialize(s:Serializer) {
    s.serialize(x);
  }

  @:keep
  function hxUnserialize(u:Unserializer) {
    x = u.unserialize();
    y = -1;
  }
}

이 예에서는 멤버 변수 y의 값을 무시하고 직렬화하지 않기로 결정했습니다. 대신 hxUnserialize에서 -1로 기본값을 정합니다. 두 메서드 모두 @:keep 메타데이터로 표시되어 코드에서 제대로 참조되지 않으므로 죽은 코드 제거(dead code elimination)가 제거하지 않게 합니다.

자세한 내용은 SerializerUnserializer API 문서를 참조하세요.

출처: Serialization

더 알아보기