2013-08-01 3 views
8

Я пытаюсь получить некоторые данные из Интернета. Данные передаются либо как объект JSON, либо XML: в обоих случаях я хотел бы не строить модель на основе структуры этого XML/JSON, а просто извлекать нужные мне данные.Получить анонимный тип из Интернета в C#

HttpResponseMessage response = await client.PostAsync(
"http://www.someAPI.com/api.xml", 
requestContent); 

response.EnsureSuccessStatusCode(); 

HttpContent content = response.Content; 

Если я должен построить модель, основанную на структуре данных я получить обратно, я сделаю это: Я просто хочу знать, если есть какая-то альтернатива. Могу ли я разобрать content как анонимный тип и, скажем, получить данные как произвольные поля или свойства или индексы массивов?

Предположим: response.Countries[5].CountryId. Возможно ли это в любом из этих двух типов (JSON и XML)? Как мне это сделать?

+0

Вы должны переформулировать свои вопросы: как сейчас, ответы ** Да ** и ** Да **. Но я думаю, это не поможет вам так много. – Andreas

+1

Вы можете попробовать присвоить содержимое, которое вы вернетесь, в переменную [dynamic] (http://msdn.microsoft.com/en-us/library/dd264741.aspx) и получить доступ к свойствам/значениям, которые есть, но, d знать заранее, что имена свойств –

+0

, конечно, я уже знаю структуру данных. Я просто не хочу строить над ним модель. – Saturnix

ответ

17

EDIT # 2:

Я добавил примечание ниже об использовании отличной Json.NET библиотеки для десериализации в dynamic объекта.


EDIT # 1:

Благодаря Hoghweed's answer, мой ответ ниже теперь более полно. В частности, мы должны гипсаHttpContent мы получаем от HttpResponseMessage.Content к ExpandoObject для того, чтобы dynamic -ness работать, как ожидалось:

dynamic content = response.Content.ReadAsAsync<ExpandoObject>().Result; 
var myPropertyValue = content.MyProperty; 

Чтобы получить метод ReadAsync<T>() расширения, хотя, вы должны были бы использовать NuGet загрузить и установить System.Net.Http.Formatting.dll из пакета Microsoft.AspNet.WebApi.Client (here's the "old" Nuget page, в котором упоминается, что он теперь включен в вышеуказанный пакет).


Оригинал Ответ:

Таким образом, вы не хотите, чтобы создать POCO и должны управлять его свойства как структура XML/JSON вы получаете обратно изменения. dynamic кажется, идеально подходит для вашего случая использования:

HttpResponseMessage response = await client.PostAsync(
"http://www.someAPI.com/api.xml", requestContent); 

response.EnsureSuccessStatusCode(); 

dynamic content = response.Content.ReadAsAsync<ExpandoObject>().Result; // Notice the use of the dynamic keyword 
var myPropertyValue = content.MyProperty; // Compiles just fine, retrieves the value of this at runtime (as long as it exists, of course) 

частности относительно XML: вы могли бы попробовать Anoop Madhusudanan's ElasticObject, которые могли бы быть очень полезным при преобразовании между dynamic и XML и обратно.

В частности в отношении JSON: вы могли бы использовать Json.NET сделать что-то вроде этого:

dynamic content = JsonConvert.DeserializeObject(response.Content.ReadAsStringAsync().Result); 
var myPropertyValue = content.MyProperty; 

Повышающий сторона в том, что вы не будете принимать зависимость от Microsoft.AspNet.WebApi.Client пакета (который, по состоянию на v4.0.30506.0, зависит от Json.NET). Недостатком является то, что вы не сможете использовать это для XML.

Надеюсь, это поможет.

+0

['ExpandoObject'] (http://blogs.msdn.com/b/csharpfaq/ архив/2009/10/01/dynamic-in-c-4-0-introduction-the-expandoobject.aspx? Redirected = true) кажется официальным ответом .NET 4.0 на такие вещи, как «ElasticObject». – anaximander

+0

Yup - но «ElasticObject» активно развивается, тогда как обновления «ExpandoObject» привязаны к новым выпускам платформы .NET (хотя это [выглядит изменяться] »(http://msdn.microsoft.com/en- нас/библиотека/dn151288.aspx)). Это также зависит от того, разрешено ли OP использовать стороннее программное обеспечение или нет. –

+0

Большое спасибо за вашу помощь. У меня возникают некоторые проблемы с моим кодом, который не компилируется прямо сейчас, но я проверю решение, которое вы отправили, как только смогу, и пометьте свой ответ. – Saturnix

2

Чтение HttpResponseMessage.Content как динамического это возможно, но не доступ это непосредственно как динамические, но с помощью соответствующего метода расширения читать его содержание, как ExpandoObject.

я написал тест поведения для этого, это ясно, это испытание, но контекст похож на то, что Ваш вопрос:

  1. объект ответ с содержанием JSon (я использовал JSON в моем тест)
  2. динамическое разрешение без объекта модели

испытание структурирована следующим образом:

  1. Учитывая анонимный объект
  2. При создании HttpResponseMessage с содержанием этого объекта с помощью JsonMedia Formatter
  3. Тогда можно получить к нему доступ, как динамический, используя ExpandoObject

Теста условием является установка Microsoft.AspNet.WebApi.Client Итак, это код теста

public class RetrieveAnonymousTypeFromTheWebInCSharp 
    : BehaviorTest 
{ 
    private object _testModel; 
    private HttpResponseMessage _message; 

    protected override void Given() 
    { 
     _testModel = new 
      { 
       Id = 14, 
       MyProperty = "Test property value" 
      }; 
    } 

    protected override void When() 
    { 
     _message = new HttpResponseMessage(HttpStatusCode.Accepted) 
         { 
          Content = 
           new ObjectContent(_testModel.GetType(), 
               _testModel, 
               new JsonMediaTypeFormatter 
                ()) 
         }; 
    } 

    [Test] 
    public void Then() 
    { 
     //then properties could be retrieved back by dynamics 
     dynamic content = _message.Content.ReadAsAsync<ExpandoObject>().Result; 
     var propertyvalue = content.MyProperty; 
     Assert.That(propertyvalue, Is.Not.Null.And.EqualTo("Test property value")); 
    } 
} 

Это может быть сделано уверен в XML тоже.

+0

Интересно, так что все, что нужно, это '.ReadAsAsync (). Результат« получить HttpContent' как 'dynamic'? –

+0

Да, я использовал его и ждал результата на месте, считывая результат, который блокирует Thread, пока результат не будет выполнен, но вы можете использовать слишком продолжение. Но важно то, что, читая его как ExpandoObject, вы можете читать его как динамическое, делая то, что было вашим намерением – Hoghweed

Смежные вопросы