反序列化Json XYZ点

本文关键字:XYZ Json 反序列化 | 更新日期: 2023-09-27 18:19:18

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 ":{"Y","Z":-1000.0:-100.0,"X":-100.0},"bboxmax":{"Y","Z":-0.1:100.0,"X":100.0}},"tg":{"开斋节":"666470","文本":"作:吻我"}}

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

反序列化方法
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;
}

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

编辑:精确牛顿。JSon输出

{"点":{" bboxmin ":{"Y","Z":-1000.0:-100.0,"X":-100.0},"bboxmax":{"Y","Z":-0.1:100.0,"X":100.0},"sboxmin":{"Y","Z":-10.277690406517843:-13.533464566929133,"X":-13.389107611548557},"sboxmax":{"Y","Z":16.510826771653544:13.533464566929133,"X":13.389107611548557},"vorEyP":{"Y","Z":30.114082470913921:34.471718543415037,"X":-7.7202528373680934},"vorFwD":{"Y","Z":-0.57735026918962573:-0.57735026918962584,"X":0.57735026918962573},"vorUP":{"Y","Z":0.816496580927726:-0.408248290463863,"X":0.40824829046386296},"v3dname":"arch_moustfa - 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
    }
}

反序列化Json XYZ点

OK,这里的问题似乎是Revit中的XYZ类是不可变的,因此JsonSerializer无法设置属性。在正常情况下,处理这个问题的方法是用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/和这里:我如何改变属性名称时,与Json.net序列化?

解决方案# 2

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

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如下所示:

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

此格式可能更好,也可能更差;您是否正在尝试将文件读写到某些预先存在的第三方库?)

第二次解决方案更新

为了调用转换器,您需要创建具有适当设置的JsonSerializer,简单地执行new JsonSerializer()将不起作用。我测试了以下内容,它工作得很好(这里我的版本的类Points只有4个字段):

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输出非常简单和可读:

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

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