Como desserializar um objeto JObject para .NET

241

Felizmente, uso a biblioteca JSON da Newtonsoft . Por exemplo, eu criaria a JObjectpartir de um objeto .NET, neste caso, uma instância de Exception (pode ou não ser uma subclasse)

if (result is Exception)
    var jobjectInstance = JObject.FromObject(result);

agora eu sei que a biblioteca pode desserializar o texto JSON (ou seja, uma string) para um objeto

// only works for text (string)
Exception exception = JsonConvert.DeserializeObject<Exception>(jsontext); 

mas o que estou procurando é:

// now i do already have an JObject instance
Exception exception = jobjectInstance.????

Bem, está claro que eu posso JObjectvoltar ao texto JSON e usar a funcionalidade desserializar, mas isso me parece inverso.

Sebastian
fonte

Respostas:

489

De acordo com este post , agora está muito melhor:

// pick out one album
JObject jalbum = albums[0] as JObject;

// Copy to a static Album instance
Album album = jalbum.ToObject<Album>();

Documentation: Converter JSON em um tipo

Tien Do
fonte
10
Alguma idéia sobre as implicações de desempenho aqui? A reflexão será usada sempre?
Shaun Rowan
1
É possível fazer isso com um JsonConverter personalizado?
Justin Skiles
3
Obrigado pela dica. Isto me ajudou bastante. Deixe-me acrescentar algo: em um método genérico em que estou usando o tipo T, era necessário result=(value is JObject) ? ((JObject)value).ToObject<T>() : (T)default(T);convertê-lo com êxito (nota - valueé um objeto proveniente de um banco de dados que pode ser um JObject ou qualquer outra coisa, caso em que o resultado deve ser nulo).
Matt
@ShaunRowan Brincando com o código no Linqpad, parece que a reflexão é usada para corresponder à propriedade no mesmo "nível" do objeto de destino que o campo correspondente no objeto JSON. O nome da sua propriedade deve corresponder ao nome do campo JSON e o tipo da sua propriedade deve ser um tipo compatível.
BobbyA
e use jobject.ToObject(myObject.GetType())se você não souber o tipo de objeto.
Tohid em 23/03
45

A partir da documentação que encontrei

JObject o = new JObject(
   new JProperty("Name", "John Smith"),
   new JProperty("BirthDate", new DateTime(1983, 3, 20))
);

JsonSerializer serializer = new JsonSerializer();
Person p = (Person)serializer.Deserialize(new JTokenReader(o), typeof(Person));

Console.WriteLine(p.Name);

A definição de classe para Persondeve ser compatível com o seguinte:

class Person {
    public string Name { get; internal set; }
    public DateTime BirthDate { get; internal set; }
}

Editar

Se você está usando uma versão recente do JSON.net e não precisa de serialização personalizada, consulte a resposta da TienDo acima (ou abaixo, se você me aprovou: P), o que é mais conciso.

Sebastian
fonte
2
Eu precisava usar essa abordagem, e não a abreviação, para poder passar configurações personalizadas de serialização.
23615 Justin Caldicott
Ans exato que estou procurando
Mark-VII
2

Tarde demais, para o caso de alguém procurar outra maneira:

void Main()
{
    string jsonString = @"{
  'Stores': [
    'Lambton Quay',
    'Willis Street'
  ],
  'Manufacturers': [
    {
      'Name': 'Acme Co',
      'Products': [
        {
          'Name': 'Anvil',
          'Price': 50
        }
      ]
    },
    {
      'Name': 'Contoso',
      'Products': [
        {
          'Name': 'Elbow Grease',
          'Price': 99.95
        },
        {
          'Name': 'Headlight Fluid',
          'Price': 4
        }
      ]
    }
  ]
}";

    Product product = new Product();
    //Serializing to Object
    Product obj = JObject.Parse(jsonString).SelectToken("$.Manufacturers[?(@.Name == 'Acme Co' && @.Name != 'Contoso')]").ToObject<Product>();

    Console.WriteLine(obj);
}


public class Product
{
    public string Name { get; set; }
    public decimal Price { get; set; }
}
Ivan Lopez
fonte
Parece exatamente com a resposta aceita .
jpaugh 3/03