.NET сериализация данных JSON с динамической структурой (схема) - PullRequest
1 голос
/ 01 мая 2011

Веб-сервис, который я использую, отвечает данными json.

это дает resultObject в виде массива: resultObject: [{object1}, {object2}, ...] если существует более одного объекта и он возвращается resultObject: {object1 }, если существует только один объект.

для сериализации в .NET Я создал «статическую» структуру классов для сопоставления схемы JSON. Но если в одном случае у меня есть массив (список) объектов, а в другом случае только один объект, как можно справиться с этой ситуацией?

Ответы [ 2 ]

1 голос
/ 02 мая 2011

Я нашел множество уродливых решений для этого, но до сих пор идет речь:

Если вы используете System.Web.Script.Serialization.JavaScriptSerializer, у вас очень ограниченный контроль.Если тип данных результата прост, вы можете просто использовать метод DeserializeObject;он переведет все в словарь, и свойство «resultObject» в первом случае будет словарём, а во втором случае оно превратится в массив такого словаря.Это не избавит вас от головной боли при окончательном переводе, но вы получите данные в словарях, которые можно считать первым шагом.

Я также попытался использовать KnownTypes и DataContractJsonSerializer, но, увы, сериализатор данныхнуждается в «подсказках» в форме специально названных свойств, чтобы помочь его десериализации.( Почему я неправильно использую атрибут KnownType? ).Это безнадежная стратегия, если вы не имеете никакого контроля над сериализацией, что, я думаю, имеет место для вас.

Итак, теперь мы подошли к уродливым решениям, выбор которых методом проб и ошибок является моим первым выбором: при использовании ScriptSerializer преобразование завершится неудачно с InvalidOperationException, если что-то не так.Затем я создал два типа данных, один с массивами данных, а другой - с данными как единым экземпляром (DataClass - мое изобретение, поскольку вы не указываете типы данных):

    [DataContract]
    public class DataClass
    {
        [DataMember]
        public string FirstName { get; set; }
        [DataMember]
        public int BirthYear { get; set; }

        public override string ToString()
        {
            return "FirstName : '" + FirstName + "', BirthYear: " + BirthYear;
        }
    }

    [DataContract]
    public class ResultSingle 
    {
        [DataMember]
        public DataClass Data { get; set; }
    }

    [DataContract]
    public class ResultArray 
    {
        [DataMember]
        public List<DataClass> Data { get; set; }
    }

Использование этих типов данныхперевод можно выполнить с помощью

        JavaScriptSerializer jSer = new JavaScriptSerializer();
        var one = jSer.Deserialize<ResultSingle>(jsonWithSingleInstance);
        var many = jSer.Deserialize<ResultArray>(jsonWithArray);

Но для этого, конечно, необходимо заранее знать тип данных, и вы получите два разных типа результатов.Вместо этого вы можете всегда конвертировать в ResultArray.Если вы получили исключение, вы должны преобразовать как ResultSingle, а затем создать экземпляр ResultArray и вручную добавить объект данных в список данных:

    static ResultArray ConvertJson(string json)
    {
        ResultArray fromJson;
        JavaScriptSerializer jSer = new JavaScriptSerializer();
        try
        {
            fromJson = jSer.Deserialize<ResultArray>(json);
            return fromJson;
        }
        catch (InvalidOperationException)
        {
            var single = jSer.Deserialize<ResultSingle> (json);
            fromJson = new ResultArray();
            fromJson.Data = new List<DataClass>();
            fromJson.Data.Add(single.Data);
            return fromJson;
        }
    }

    static void Main(string[] args)
    {
        var jsonWithSingleInstance = "{\"Data\":{\"FirstName\":\"Knud\",\"BirthYear\":1928}}";
        var jsonWithArray = "{\"Data\":[{\"FirstName\":\"Knud\",\"BirthYear\":1928},{\"FirstName\":\"Svend\",\"BirthYear\":1930}]}";

        var single = ConvertJson(jsonWithSingleInstance);
        var array = ConvertJson(jsonWithArray);
    }

Я не говорю, что это красивое решение (это не так), но это должно сработать.

Вы также можете посмотреть на json.net, который, кажется, является предпочтительным сериализатором json в .NET: Как установить JSON.NET с помощью NuGet?

0 голосов
/ 03 мая 2011

Ну, мой поставщик услуг наконец сказал, что это действительно ошибка.

http://jira.codehaus.org/browse/JETTISON-102

говорит, что это из-за версии Java, которую они используют.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...