Десериализовать точку Json XYZ

Разработка Autodesk Revit

Я сериализовал точку 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), что является результатом невозможности проанализировать прочитанные значения до их уступчивого типа.

Метод десериализации

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

Хотел бы я найти хороший способ преобразовать и переопределить этот беспорядок.

Редактировать: Exact 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}, "Ворейп": {"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},"5gs-fa46386296},"5-fa-Moust":"1Arch_Moustname" ":{"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
    }
}

person M.Khalil    schedule 24.08.2014    source источник
comment
Ваш Json недействителен согласно jsonformatter.curiousconcept.com. Ошибки включают дополнительное закрытие } в конце файла. Вы вставили все выходные данные Json или некоторые из них были пропущены?   -  person dbc    schedule 24.08.2014
comment
пропустил некоторые, чтобы было проще..если вы видите, что необходимо поставить все это...я сделаю?   -  person M.Khalil    schedule 24.08.2014
comment
Я бы предложил сделать минимальный, полный и поддающийся проверке пример вашей проблемы. Если ваш Json не анализируется, потому что вы скопировали его не полностью, значит, он неполный или не поддающийся проверке.   -  person dbc    schedule 24.08.2014
comment
хорошо, я обновлю Json OutPut   -  person M.Khalil    schedule 24.08.2014
comment
я также добавил остальные классы для большего пояснения.   -  person M.Khalil    schedule 24.08.2014


Ответы (1)


Хорошо, проблема в том, что класс XYZ в Revit является неизменяемым, поэтому JsonSerializer не может устанавливать свойства . При нормальных обстоятельствах способ справиться с этим — украсьте соответствующий конструктор для вашего класса с помощью JsonConstructorAttribute, но вы не можете этого сделать, потому что XYZ — это класс Revit, а не ваш собственный.

Решение №1

Чтобы обойти эту проблему, вы можете подклассировать XYZ и украсить соответствующий конструктор атрибутом, однако я не уверен, запечатан ли класс Revit или могут ли это иметь непредвиденные побочные эффекты, если вы действительно передадите один из этих подклассов XYX. вернуться в Ревит. В качестве альтернативы вы можете ввести прокси-класс исключительно для сериализации и десериализации:

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

В качестве альтернативы вы можете попробовать написать свой собственный JsonConverter для XYZ, а затем зарегистрировать его в 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]}

Это позволяет избежать использования прокси-серверов и, вероятно, является более привлекательным решением.

person dbc    schedule 24.08.2014
comment
Что касается вашего последнего вопроса, нет, я не буду использовать его с 3D-частью, на самом деле я хочу экспортировать некоторые крошечные задачи из Revit для отправки через Интернет другому пользователю, что составляет около 8 КБ или что-то вроде отправки всего файла размером 160 МБ. Я попробовал 1-е решение, и оно прекрасно работает... теперь пробую второе. я хотел бы, чтобы вы могли подсказать мне, как использовать JSonConverter, если вы знаете некоторые сайты с дружественной иллюстрацией, было бы неплохо. - person M.Khalil; 24.08.2014
comment
@ M.Khalil - см. Инструкции по использованию второго решения. - person dbc; 24.08.2014