2012-06-17 72 views
3

我想將一個json字符串反序列化成一個Haxe類的實例。你可以使用Haxe反序列化一個json字符串到一個類實例嗎?

這裏是一個類:

class Action 
{ 
    public var Name:String; 
    public var Id:Int; 

    public function new(id:Int, name:String) 
    { 
     Id = id; 
     Name = name; 
    } 
} 

我願做這樣的事情。

var action:Action = haxe.Json.parse(actionJson); 
trace(action.Name); 

當我嘗試這個,我得到這個錯誤。
類型錯誤:錯誤#1034:類型強制失敗:無法轉換對象@ 3431809行動

回答

4

JSON沒有一種機制來映射語言特定的數據類型,並且只支持包含在JS中的數據類型的子集。要保留有關Haxe類型的信息,您一定可以建立自己的機制。

// This works only for basic class instances but you can extend it to work with 
// any type. 
// It doesn't work with nested class instances; you can detect the required 
// types with macros (will fail for interfaces or extended classes) or keep 
// track of the types in the serialized object. 
// Also you will have problems with objects that have circular references. 

class JsonType { 
    public static function encode(o : Dynamic) { 
    // to solve some of the issues above you should iterate on all the fields, 
    // check for a non-compatible Json type and build a structure like the 
    // following before serializing 
    return haxe.Json.stringify({ 
     type : Type.getClassName(Type.getClass(o)), 
     data : o 
    }); 
    } 

    public static function decode<T>(s : String) : T { 
    var o = haxe.Json.parse(s), 
     inst = Type.createEmptyInstance(Type.resolveClass(o.type)); 
    populate(inst, o.data); 
    return inst; 
    } 

    static function populate(inst, data) { 
    for(field in Reflect.fields(data)) { 
     Reflect.setField(inst, field, Reflect.field(data, field)); 
    } 
    } 
} 
+0

(三年後)是否有haxelib來處理這個問題? – ashes999

1

您可以使用TJSON。它非常快速和輕量級。

+0

將'TJSON'解析爲特定的類嗎? – seebiscuit

3

我擴展了Franco's answer以允許在您的json對象中遞歸地包含對象,只要在該對象上設置_explicitType屬性即可。

例如,下面的JSON:

{ 
    intPropertyExample : 5, 
    stringPropertyExample : 'my string', 
    pointPropertyExample : { 
     _explicitType : 'flash.geom.Point', 
     x : 5, 
     y : 6 
    } 
} 

將正確地序列化爲一個對象的類看起來是這樣的:

import flash.geom.Point; 

class MyTestClass 
{ 
    public var intPropertyExample:Int; 
    public var stringPropertyExample:String; 
    public var pointPropertyExample:Point; 
} 

打電話時:

var serializedObject:MyTestClass = EXTJsonSerialization.decode([string of json above], MyTestClass) 

這裏的代碼(請注意,它使用TJSON作爲解析器,因爲CrazySam rec推薦):

import tjson.TJSON; 

class EXTJsonSerialization 
{ 
    public static function encode(o : Dynamic) 
    { 
     return TJSON.encode(o); 
    } 

    public static function decode<T>(s : String, typeClass : Class<Dynamic>) : T 
    { 
     var o = TJSON.parse(s); 
     var inst = Type.createEmptyInstance(typeClass); 
     EXTJsonSerialization.populate(inst, o); 
     return inst; 
    } 

    private static function populate(inst, data) 
    { 
     for (field in Reflect.fields(data)) 
     { 
      if (field == "_explicitType") 
       continue; 

      var value = Reflect.field(data, field); 
      var valueType = Type.getClass(value); 
      var valueTypeString:String = Type.getClassName(valueType); 
      var isValueObject:Bool = Reflect.isObject(value) && valueTypeString != "String"; 
      var valueExplicitType:String = null; 

      if (isValueObject) 
      { 
       valueExplicitType = Reflect.field(value, "_explicitType"); 
       if (valueExplicitType == null && valueTypeString == "Array") 
        valueExplicitType = "Array"; 
      } 

      if (valueExplicitType != null) 
      { 
       var fieldInst = Type.createEmptyInstance(Type.resolveClass(valueExplicitType)); 
       populate(fieldInst, value); 
       Reflect.setField(inst, field, fieldInst); 
      } 
      else 
      { 
       Reflect.setField(inst, field, value); 
      } 
     } 
    } 
} 
+0

請注意,上面的代碼適用於Flash目標,但對於本機目標,您需要做一些棘手的事情來處理數組。 [this gist](https://gist.github.com/DrSkipper/9042123#file-extjsonserialization-hx)中的代碼應該能夠處理這種情況。 –

相關問題