Преобразование XML без каких-либо атрибутов/метаданных в объект .NET

У меня есть объект, и я преобразовываю его в XML, используя модифицированный DataContractSerializer.

Я удаляю все метаданные/пространства имен и т. д., так что результат просто:

<myObject> <someProperty>5</someProperty> <mySubObjects> <mySubObject>...</mySubObject> <mySubObject>...</mySubObject> ... </myObject>

и т.п.

Интересно, можно ли вернуть это обратно в объекты.

Я смог частично сделать это, используя JSON.NET, чтобы преобразовать его в JSon, который работает, но есть проблема с десериализацией JSon и списков, которую я не мог понять, несмотря на то, что прочитал несколько объяснений об этом на SO.

XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
string jsonText = JsonConvert.SerializeXmlNode(doc, Newtonsoft.Json.Formatting.None, true);
var obj = JsonConvert.DeserializeObject<T>(jsonText);

Невозможно десериализовать текущий объект JSON (например, {"name":"value"}) в тип '...', поскольку для правильной десериализации этого типа требуется массив JSON (например, [1,2,3]). Чтобы исправить эту ошибку, либо измените JSON на массив JSON (например, [1,2,3]), либо измените десериализованный тип, чтобы он был обычным типом .NET (например, не примитивный тип, такой как целое число, а не тип коллекции, такой как массив или список), который можно десериализовать из объекта JSON. JsonObjectAttribute также можно добавить к типу, чтобы заставить его десериализоваться из объекта JSON.

Должно быть более прямое решение, никогда не будет проблемы с попыткой сделать недопустимое приведение, поскольку исходные данные также поступают от объекта, какая-то библиотека сопоставления или что-то еще должно позаботиться об этом. Любые идеи?


person NibblyPig    schedule 22.07.2014    source источник
comment
Мне непонятно, что вы пытаетесь сделать. Что вы имеете в виду, говоря, что возвращаете это обратно в объекты? Вы сказали, что пробовали что-то с использованием JSON, но он ноет о списках и IEnumerables, что мало что говорит нам о том, что вы пытались сделать.   -  person Moby Disk    schedule 22.07.2014
comment
Игнорируйте часть JSON, я хочу преобразовать XML в объект. Поскольку метаданных нет, я не думаю, что XmlSerializer будет работать (когда я пытаюсь, я получаю сообщение об ошибке «недопустимый xml», но я могу поместить XML в XmlDocument, поэтому он должен быть действительным). Я думаю, мне просто нужно что-то, чтобы перебирать и сопоставлять каждую запись с объектом, но это должно быть достаточно умно, чтобы иметь дело со списками. Я немного уточнил свой вопрос (сегодня очень напряженный!)   -  person NibblyPig    schedule 22.07.2014
comment
Эта структура выглядит так, как будто вы вполне можете использовать XMLSerilizer. Он может обрабатывать массивы, списки и тому подобное. Вам просто нужно создать классы, соответствующие имеющейся у вас структуре. Есть атрибуты, которые вы добавляете к классам, которые сообщают имена тегов. Используя ваш пример в качестве руководства, вам понадобится класс с именем myObject с целочисленным свойством, называемым someProperty. Затем ему потребуется массив или список «mySubObject» с именем mySubObjects.   -  person Moby Disk    schedule 22.07.2014
comment
Да, это то, что у меня есть, поскольку исходный XML исходит из десериализуемого объекта, лишен любых метаданных и т. д., а затем используется для воссоздания объекта. Я просто получаю сообщение об ошибке There is an error in XML document (1, 133). {"Input string was not in a correct format."} без каких-либо объяснений того, почему это неправильный формат. Интересно, делает ли он недопустимый бросок? Поскольку у него нет никакой информации о типах данных.   -  person NibblyPig    schedule 22.07.2014
comment
Итак, вы хотите воссоздать объект, даже если вы лишили его метаданных? Я не уверен, что это значит, но это кажется невозможным.   -  person Moby Disk    schedule 22.07.2014


Ответы (1)


Изменить: согласно комментариям, вот как вы могли бы это сделать без необходимости конвертировать в JSON.

string xml = "<myObject>\n" +
             "  <someProperty>5</someProperty>\n" +
             "  <mySubObjects>\n" +
             "      <mySubObject>test</mySubObject>\n" +
             "      <mySubObject>test</mySubObject>\n" +
             "  </mySubObjects>\n" +
             "</myObject>\n";

using (TextReader reader = new StringReader(xml))
{
    XmlSerializer serializer = new XmlSerializer(typeof(myObject));
    var obj = serializer.Deserialize(reader);

}

Вспомогательный класс:

[Serializable()]
public class myObject
{
    [XmlElement("someProperty")]
    public string someProperty { get; set; }

    [XmlArray("mySubObjects")]
    [XmlArrayItem("mySubObject", typeof(string))]
    public List<string> mySubObjects { get; set; }
}

******Предыдущий ответ в формате JSON:********

Этот код должен сделать это за вас:

string xml = "<myObject>\n" +
             "  <someProperty>5</someProperty>\n" +
             "  <mySubObjects>\n" +
             "      <mySubObject>test</mySubObject>\n" +
             "      <mySubObject>test</mySubObject>\n" +
             "  </mySubObjects>\n" +
             "</myObject>\n";
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
string jsonText = JsonConvert.SerializeXmlNode(doc);
var obj = JsonConvert.DeserializeObject<RootObject>(jsonText);

Вот вспомогательные классы:

public class MySubObjects
{
    public List<string> mySubObject { get; set; }
}

public class MyObject
{
    public string someProperty { get; set; }
    public MySubObjects mySubObjects { get; set; }
}

public class RootObject
{
    public MyObject myObject { get; set; }
}

Проблема, с которой вы столкнулись, заключалась в том, что он пытался преобразовать mySubObjects в класс вместо списка. Это потому, что он видит каждый mySubObject как сам объект. Создав класс и предоставив список как свойство, JSON.Net может затем добавить каждый mySubObject в открытый список. Под изменением массива JSON подразумевается полное удаление узла mySubObjects и просто использование нескольких файлов . Затем JSON.Net увидит его как массив и преобразует его непосредственно в список вместо того, чтобы инкапсулировать его в отдельный класс. Надеюсь, я правильно объяснил.

person Cory    schedule 22.07.2014
comment
Я вижу, в этом есть смысл. Но я не могу изменить формат. Может быть, есть какие-то атрибуты метаданных, которые я могу использовать, чтобы сказать, что это List<T>, без написания какого-то сложного пользовательского класса десериализатора? Если нет, возможно, придется просто отказаться от этого и, возможно, просто сохранить xml, не удаляя все метаданные. - person NibblyPig; 22.07.2014
comment
Пожалуйста, смотрите мое редактирование выше. Я думаю, это сработает для вас. Он пропускает необходимость использования JSON и преобразует его с помощью XmlSerializer. Таким образом, вам нужен только один класс. - person Cory; 22.07.2014