反序列化Json XYZ点 [英] Deserialize Json XYZ Point

查看:308
本文介绍了反序列化Json XYZ点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Autodesk Revit开发

我将XYZ点从一个类(点)从容器(点和标签)序列化到文件.

I serialized an XYZ point form a class (Points) from a container (Points and Tags) to a file.

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:Kiss me}}

{"Points":{"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: Kiss me"}}

反序列化时,所有点的结果都为(0.0,0.0,0.0),这是由于无法将读取的值解析为适当的类型.

on deserializing i got the results for all the points to a value of (0.0,0.0,0.0) which is a result of unable to parse read values to its propitiate type.

反序列化方法

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;
}

我希望我能找到一种转换和覆盖此混乱状态的好方法.

I wish i could find a way a good way to convert and override this mess.

确切的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",来源":{"Z":1154.5239372729186,"Y":1164.3934060532893,"X":-1119.6229882673815},文本":"coor:Kiss me", "ledelbo":{"Z":1157.6807845880096,"Y":1163.9955344285622,"X":-1116.8640125770175}}}

{"Points":{"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"},"Tags":{"eId":"666470","origin":{"Z":1154.5239372729186,"Y":1164.3934060532893,"X":-1119.6229882673815},"text":"coor: Kiss me","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
    }
}

推荐答案

好的,这里的问题似乎是使用JsonConstructorAttribute 为您的类装饰适当的构造函数-但您不能这样做,因为XYZ Revit 类,而不是您自己的类.

OK, the problem here seems to be that the XYZ class in Revit is immutable, so the JsonSerializer cannot set the properties. Under normal circumstances the way to deal with this is to decorate an appropriate constructor for your class with JsonConstructorAttribute - but you cannot do that because XYZ is a Revit class, not your own.

解决方案1 ​​

要变通解决此问题,您可以将XYZ子类化,并使用属性装饰适当的构造函数-但是,我不确定Revit类是否已密封,或者如果您实际通过了它,是否会产生无法预料的副作用这些子XYX之一返回到Revit.另外,您可以引入纯粹用于序列化和反序列化的代理类:

To work around this problem, you could subclass XYZ and decorate the appropriate constructor with the attribute - however, I'm not sure whether the Revit class is sealed, or whether this could have unforseen side effects if you actually pass one of these subclased XYXs back to Revit. Alternatively, you could introduce a proxy class purely for serialization and deserialization:

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序列化代理,而不是原始属性:

Having done this, you can then add proxy properties to your custom classes, mark them hidden in the debugger, and tell Json.Net to serialize the proxies, not the original properties:

[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/和此处:在使用Json进行序列化时如何更改属性名称.净吗?

More information here: http://www.tecsupra.com/serializing-only-some-properties-of-an-object-to-json-using-newtonsoft-json-net/ and here: How can I change property names when serializing with Json.net?

解决方案2

或者,您可以尝试编写自己的JsonConverter (XYZ),然后将其注册到Json.Net .转换器可能看起来像这样(警告-未经测试!)

Alternatively, you might try writing your own JsonConverter for XYZ and then registering it with Json.Net. The converter might look something like this (warning - not tested!)

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();
    }
}

这将产生如下所示的Json:

which would produce Json that looks like this:

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

此格式可能会更好或更坏;您是否正在尝试向先前存在的第三方库读写文件?]

This format might be better or worse; are you trying to read and write files to some pre-existing 3rd party library?]

第二个解决方案更新

您需要使用适当的设置来创建JsonSerializer以便调用转换器,简单地执行new JsonSerializer()将不起作用.我测试了以下内容,并且工作正常(此处我的班级Points版本只有4个字段):

You need to create the JsonSerializer with the appropriate settings in order to invoke the converter, simply doing new JsonSerializer() will not work. I tested the following and it works fine (here my version of your class Points has only 4 fields):

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());
        }
    }
}

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

The Json output produced is quite simple and readable:

{"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]}

这避免了代理的需求,因此可能是更漂亮的解决方案.

This avoids the requirement for proxies and so is probably a prettier solution.

这篇关于反序列化Json XYZ点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆