Home > Enterprise >  How can I deserialize a JSON to a .NET object with several List<T> parameters?
How can I deserialize a JSON to a .NET object with several List<T> parameters?

Time:12-23

I'm using this library (FireSharp) to access Firebase. I've retrieved a json as the body of a FirebaseResponse (status and body basically), which works good and looks like this (all test data):

"{\"Cobros\":{\"1001\":{\"Estado\":\"Cobrado\",\"Repartidor\":124},\"1112\":{\"Estado\":\"Pendiente\",\"Repartidor\":124}},\"Pedidos\":{\"1111\":{\"Estado\":\"Entregado\",\"Repartidor\":123}},\"Repartidores\":{\"123\":{\"ID Android\":\"asdadada\",\"Terminal\":123},\"124\":{\"ID Android\":\"dggrefawe\",\"Terminal\":124}}}"

The Firebase struct looks like this, leafs with some params behind that. I need to deserialize the Json to embed it into a Object with several List params, one for each node behind 18500. I've checked this question and this is my code so far:

    public class cargaFirebase
    {
        [JsonProperty("Cobros")]
        public List<documentoFirebase> carfb_cobros { get; set; }
        [JsonProperty("Pedidos")]
        public List<documentoFirebase> carfb_pedidos { get; set; }
        [JsonProperty("Repartidores")]
        public List<repartidorFirebase> carfb_repartidores { get; set; }
    }

And the deserialization try...

FirebaseResponse resp = fbClient.Get(request);
cargaFirebase carga_res = JsonConvert.DeserializeObject<cargaFirebase>(resp.Body);

This gives me a deesrialization error I can't understand, not really into jsons sorry, and thx in advanced!

{Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[Reparto_Android.Code.Helpers.FirebaseHelper documentoFirebase]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly. To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object. Path

CodePudding user response:

this code works properly

cargaFirebase carga_res = JsonConvert.DeserializeObject<CargaFirebase>(resp.Body);

if you use these classes

 public partial class CargaFirebase
    {
        [JsonProperty("Cobros")]
        public Dictionary<string, Cobro> Cobros { get; set; }

        [JsonProperty("Pedidos")]
        public Pedidos Pedidos { get; set; }

        [JsonProperty("Repartidores")]
        public Dictionary<string, Repartidore> Repartidores { get; set; }
    }

    public partial class Cobro
    {
        [JsonProperty("Estado")]
        public string Estado { get; set; }

        [JsonProperty("Repartidor")]
        public long Repartidor { get; set; }
    }

    public partial class Pedidos
    {
        [JsonProperty("1111")]
        public Cobro The1111 { get; set; }
    }

    public partial class Repartidore
    {
        [JsonProperty("ID Android")]
        public string IdAndroid { get; set; }

        [JsonProperty("Terminal")]
        public long Terminal { get; set; }
    }

output

{
  "Cobros": {
    "1001": {
      "Estado": "Cobrado",
      "Repartidor": 124
    },
    "1112": {
      "Estado": "Pendiente",
      "Repartidor": 124
    }
  },
  "Pedidos": {
    "1111": {
      "Estado": "Entregado",
      "Repartidor": 123
    }
  },
  "Repartidores": {
    "123": {
      "ID Android": "asdadada",
      "Terminal": 123
    },
    "124": {
      "ID Android": "dggrefawe",
      "Terminal": 124
    }
  }
}

CodePudding user response:

If all those leaf names, such as "1111", "1001", "1112", are dynamically generated and you want to ignore them, maybe you can try some customized json converters like below:

public class CargaFirebase
{
    [JsonConverter(typeof(DocumentoFirebaseConverter))]
    public List<DocumentoFirebase> Cobros { get; set;}

    [JsonConverter(typeof(DocumentoFirebaseConverter))]
    public List<DocumentoFirebase> Pedidos { get; set;}

    [JsonConverter(typeof(RepartidorFirebaseConverter))]
    public List<RepartidorFirebase> Repartidores { get; set; }

}

public class DocumentoFirebase
{
    public string Estado { get; set; }
    public int Repartidor { get; set; }
}

public class RepartidorFirebase
{
    [JsonProperty(PropertyName = "Id Android")]
    public string Id_Android { get; set; }
    public int Terminal { get; set; }
}

class DocumentoFirebaseConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(List<DocumentoFirebase>);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var jObj = JObject.Load(reader);
        List<DocumentoFirebase> docs = new List<DocumentoFirebase>();
        foreach (JProperty prop in jObj.Properties())
        {
            var doc = prop.Value.ToObject<DocumentoFirebase>();
            docs.Add(doc);
        }
        return docs;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

class RepartidorFirebaseConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(List<RepartidorFirebase>);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var jObj = JObject.Load(reader);
        List<RepartidorFirebase> repartidors = new List<RepartidorFirebase>();
        foreach (JProperty prop in jObj.Properties())
        {
            var repartidor = prop.Value.ToObject<RepartidorFirebase>();
            repartidors.Add(repartidor);
        }
        return repartidors;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

Then you can try to parse the raw json as what you did before:

cargaFirebase carga_res = JsonConvert.DeserializeObject<CargaFirebase>(resp.Body);
  • Related