反序列化Json XYZ Point

时间:2014-08-24 12:52:35

标签: c# json serialization revit-api

Autodesk Revit Development

我将XYZ点从容器(点和标签)中的类(点)序列化为文件。

public class Serialize_pack
{
    public View_3D_Data v3ddata;
    public Tag_Class tg;
}

通过此方法

public static void serializeme(object classme)
{
    string coor_file = constants.SenddDir() + constants.filename();

    using (StreamWriter file = File.CreateText(coor_file))
    {
        JsonSerializer serializer = new JsonSerializer();

        serializer.Serialize(file, classme);
    }
}

我得到了这个结果

  

{ “点”:{ “bboxmin”:{ “Z”: - 1000.0, “Y”: - 100.0, “X”: - 100.0}, “bboxmax”:{ “Z”: - 0.1,“Y “:100.0,”X“:100.0}},”tg“:{”eId“:”666470“,”text“:”coor:吻我“}}

在反序列化时,我得到了所有点的结果,其值为(0.0,0.0,0.0),这是因为无法将读取值解析为其propitiate类型。

反序列化方法

public static object deserializeme(string path)
{
    Serialize_pack accquired = null;
    using (StreamReader file = File.OpenText(path))
    {
        JsonSerializer serializer = new JsonSerializer();
        accquired = (Serialize_pack)serializer.Deserialize(file, typeof(Serialize_pack));                           
    }

    return accquired;
}

我希望我能找到一种转换和覆盖这种混乱的好方法。

编辑:完全Newton.JSon OutPut

  

{ “点”:{ “bboxmin”:{ “Z”: - 1000.0, “Y”: - 100.0, “X”: - 100.0}, “bboxmax”:{ “Z”: - 0.1,“Y “:100.0,” X “:100.0},” sboxmin “:{” Z “: - 10.277690406517843,” Y “: - 13.533464566929133,” X “: - 13.389107611548557},” sboxmax “:{” Z “:16.510826771653544” Y “:13.533464566929133,” X “:13.389107611548557},” vorEyP “:{” Z “:30.114082470913921,” Y “:34.471718543415037,” X “: - 7.7202528373680934},” vorFwD “:{” Z “: - 0.57735026918962573” Y “: - 0.57735026918962584,” X “:0.57735026918962573},” vorUP “:{” Z “:0.816496580927726,” Y “: - 0.408248290463863,” X “:0.40824829046386296},” v3dname “:” Arch_Moustafa-GAJ-145834" } ,“标签”:{“eId”:“666470”,“origin”:{“Z”:1154.5239372729186,“Y”:1164.3934060532893,“X”: - 1119.6229882673815},“text”:“coor:吻我”, “ledelbo”:{ “Z”:1157.6807845880096, “Y”:1163.9955344285622, “X”: - 1116.8640125770175}}}

标记类

public class Tag
{
    public string eId;

    public XYZ origin;
    public string text;
    public XYZ ledelbo;

public void getTagdata(View v)
    {
        ///we need all the annotation to be sent.
       /// do some stuff and cast the results on the public variables

    }
}

积分等级

public class Points
{

    public XYZ bboxmin;
    public XYZ bboxmax;
    public XYZ sboxmin;
    public XYZ sboxmax;

    public XYZ vorEyP;
    public XYZ vorFwD;
    public XYZ vorUP;

    public string v3dname;


    [JsonIgnore]
    public View3D view;

 public void get3dviewdata()
    {
       ///we need all the points to be sent.
       /// do some stuff and cast the results on the public variables
    }
}

1 个答案:

答案 0 :(得分:2)

好的,这里的问题似乎是Revit中的XYZ classimmutable,因此JsonSerializer无法设置属性。在正常情况下,处理此问题的方法是decorate an appropriate constructor for your class with JsonConstructorAttribute - 但您不能这样做,因为XYZ Revit 类,而不是您自己的类。

解决方案#1

要解决此问题,您可以继承XYZ并使用该属性修饰相应的构造函数 - 但是,我不确定Revit类是否已密封,或者如果您是否可能有不可预见的副作用实际上将这些子类XYX中的一个传递回Revit。或者,您可以引入一个纯粹用于序列化和反序列化的代理类:

public static class XYZProxyExtensions
{
    public static XYZProxy ToXYZProxy(this XYZ xyz)
    {
        return new XYZProxy(xyz.X, xyz.Y, xyz.Z);
    }
}

public class XYZProxy
{
    public XYZProxy()
    {
        this.X = this.Y = this.Z = 0;
    }

    public XYZProxy(double x, double y, double z)
    {
        this.X = x;
        this.Y = y;
        this.Z = z;
    }
    public double X { get; set; }
    public double Y { get; set; }
    public double Z { get; set; }

    public XYZ ToXYZ()
    {
        return new XYZ(X, Y, Z);
    }
    public override string ToString()
    {
        return string.Format("({0},{1},{2})", X, Y, Z);
    }
}

完成此操作后,您可以将代理属性添加到自定义类中,将它们隐藏在调试器中,并告诉Json.Net序列化代理,而不是原始属性:

[JsonObject(MemberSerialization.OptIn)]
public class Points
{
    public XYZ bboxmin { get; set; }

    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    [JsonProperty(PropertyName = "bboxmin")]
    public XYZProxy bboxminProxy
    {
        get
        {
            return bboxmin.ToXYZProxy();
        }
        set
        {
            bboxmin = value.ToXYZ();
        }
    }
}

此处提供了更多信息:http://www.tecsupra.com/serializing-only-some-properties-of-an-object-to-json-using-newtonsoft-json-net/和此处:How can I change property names when serializing with Json.net?

解决方案#2

或者,您可以尝试XYZ class XYZConverter : JsonConverter { public override bool CanConvert(Type objectType) { return objectType == typeof(XYZ); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var obj = JToken.Load(reader); if (obj.Type == JTokenType.Array) { var arr = (JArray)obj; if (arr.Count == 3 && arr.All(token => token.Type == JTokenType.Float)) { return new XYZ(arr[0].Value<double>(), arr[1].Value<double>(), arr[2].Value<double>()); } } return null; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { var vector = (XYZ)value; writer.WriteStartArray(); writer.WriteValue(vector.X); writer.WriteValue(vector.Y); writer.WriteValue(vector.Z); writer.WriteEndArray(); } } ,然后writing your own JsonConverter。转换器可能看起来像这样(警告 - 未经测试!)

"bboxmin": [ -100.0, -100.0, -1000.0 ]

会生成看起来像这样的Json:

JsonSerializer

这种格式可能更好或更差;你试图读取和写入一些预先存在的第三方库吗?]

第二次解决方案更新

您需要使用适当的设置创建new JsonSerializer()才能调用转换器,只需执行Points即可。我测试了以下内容并且工作正常(这里我的班级public static class JsonSerializerTest { static JsonSerializerTest() { // This needs to be done only once, so put it in an appropriate static initializer. JsonConvert.DefaultSettings = () => new JsonSerializerSettings { Converters = new List<JsonConverter> { new XYZConverter() } }; } public static void Test() { Points points = new Points(); points.bboxmin = new XYZ(-100, -100, -1000); points.bboxmax = new XYZ( 100, 100, 1000); points.sboxmin = new XYZ(-10, -10, -100); points.sboxmax = new XYZ( 10, 10, 100); try { string json; using (var writer = new StringWriter()) { JsonSerializer serializer = JsonSerializer.CreateDefault(); serializer.Serialize(writer, points); json = writer.ToString(); } Points newPoints = null; using (var reader = new StringReader(json)) { JsonSerializer serializer = JsonSerializer.CreateDefault(); newPoints = (Points)serializer.Deserialize(reader, typeof(Points)); } Debug.Assert(points.bboxmin.IsAlmostEqualTo(newPoints.bboxmin)); Debug.Assert(points.bboxmax.IsAlmostEqualTo(newPoints.bboxmax)); Debug.Assert(points.sboxmin.IsAlmostEqualTo(newPoints.sboxmin)); Debug.Assert(points.sboxmax.IsAlmostEqualTo(newPoints.sboxmax)); } catch (Exception ex) { Debug.Assert(false, ex.ToString()); } } } 的版本只有4个字段):

{"bboxmin":[-100.0,-100.0,-1000.0],"bboxmax":[100.0,100.0,1000.0],"sboxmin":[-10.0,-10.0,-100.0],"sboxmax":[10.0,10.0,100.0]}

生成的Json输出非常简单易读:

{{1}}

这避免了对代理的要求,因此可能是一个更漂亮的解决方案。