0

How can I deserialize a JSON file that has blocks in a single class? Is there a way that I can inform what is the parent block for the attribute and the attribute using the JSON annotation in Class?

The JSON is below:

{
    "Viagem": {
        "Id": 33333,
        "NumeroAtracacao": "22/2222",
        "NumeroViagem": "02002 00303",
        "Status": "DESATRACADO",
        "Joint": "UCLA UCLA",
        "Servico": "AMERICA CENTRAL",
        "MotivoEspera": "-",
        "LiberacaoRecebimento": "21/05/2018 07:00:00",
        "Navio": {
            "Nome": "MONTE CERVANTES",
            "Armador": {
                "Id": 0,
                "CodigoGeParcei": null,
                "Nome": "ALIANCA",
                "Sigla": "ALI",
                "CnpjCpf": null,
                "Endereco": null,
                "Cep": null,
                "Site": null
            },
            "ImagemNavio": ".......",
            "Comprimento": 272.08,
            "Lloyd": 9283186,
            "CallSign": "DHTK",
            "CapacidadeTeus": 5560,
            "Shortname": "MOCER"
        },
        "ChegadaPrevista": "27/05/2018 12:00:00",
        "AtracacaoPrevista": "29/05/2018 07:00:00",
        "SaidaPrevista": "30/05/2018 19:00:00",
        "DeadLine": "25/05/2018 12:00:00"
    }
}

And this is my class that I want to use to deserialize the JSON:

namespace WS_SantosBrasil.Model
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
    using System.Data.Entity.Spatial;

    [Table("Viagem")]
    public partial class Viagem
    {
        [Key]
        [Column(Order = 0)]
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public int Id { get; set; }  

        [Key]
        [Column(Order = 1)]
        [StringLength(50)]
        public string IdCtis { get; set; }

        [StringLength(20)]
        public string NumeroAtracacao { get; set; }

        [StringLength(20)]
        public string NumeroViagem { get; set; }

        [StringLength(50)]
        public string Status { get; set; }

        [StringLength(50)]
        public string Joint { get; set; }

        [StringLength(50)]
        public string Servico { get; set; }

        [StringLength(50)]
        public string MotivoEspera { get; set; }

        [StringLength(20)]
        public string LiberacaoRecebimento { get; set; }

        [StringLength(20)]
        public string ChegadaPrevista { get; set; }

        [StringLength(20)]
        public string AtracacaoPrevista { get; set; }

        [StringLength(20)]
        public string SaidaPrevista { get; set; }

        [StringLength(20)]
        public string DeadLine { get; set; }

        [StringLength(20)]
        public string Chegada { get; set; }

        [StringLength(20)]
        public string Atracacao { get; set; }

        [StringLength(20)]
        public string Saida { get; set; }

        [StringLength(20)]
        public string InicioOperacao { get; set; }

        [StringLength(20)]
        public string FimOperacao { get; set; }

        [StringLength(50)]
        public string TipoOperacao { get; set; }

        [StringLength(20)]
        public string CodigoCodesp { get; set; }

        public decimal? CaladoAtracacao { get; set; }

        public decimal? CaladoDesatracacao { get; set; }

        [StringLength(20)]
        public string NumeroViagemImportacao { get; set; }

        [StringLength(20)]
        public string NumeroViagemExportacao { get; set; }

        [StringLength(20)]
        public string PrevisaoDescarga { get; set; }

        [StringLength(20)]
        public string PrevisaoEmbarque { get; set; }

        [StringLength(20)]
        public string PrevisaoRemocao { get; set; }

        [StringLength(50)]
        public string LocalAtracacao { get; set; }

        [StringLength(100)]
        public string Navio_Nome { get; set; }

        public string ImagemNavio { get; set; }

        public decimal? Navio_Comprimento { get; set; }

        [StringLength(20)]
        public string Navio_Lloyd { get; set; }

        [StringLength(50)]
        public string Navio_CallSign { get; set; }

        public int? Navio_CapacidadeTeus { get; set; }

        [StringLength(20)]
        public string Navio_Shortname { get; set; }

        public int? Armador_Id { get; set; }

        [StringLength(20)]
        public string Armador_CodigoGeParcei { get; set; }

        [StringLength(100)]
        public string Armador_Nome { get; set; }

        [StringLength(10)]
        public string Armador_Sigla { get; set; }

        [StringLength(20)]
        public string Armador_CnpjCpf { get; set; }

        [StringLength(100)]
        public string Armador_Endereco { get; set; }

        [StringLength(20)]
        public string Armador_Cep { get; set; }

        [StringLength(100)]
        public string Armador_Site { get; set; }

        public virtual ContainerViagem ContainerViagem { get; set; }
    }
}

How can I inform when deserializing the JSON for this class, that the attribute Nome_Navio, for example, is inside block Navio and that the JSON attribute is NOME?

Jairo Franchi
  • 367
  • 1
  • 2
  • 13
  • Wrap it in another class, for example: `public class Wrapper { public Viagem Viagem { get; set; }}` – DavidG Jul 26 '18 at 13:16
  • As other said, you might want to Desialize the JSON string into it's proper class before placing the information into your Viagem class. Is there anything preventing you from doing that? Visual studio can automaticly generate the needed class from your JSON File (copy the JSON content and do a Edition / special paste / "Copy JSON code as Class") – Maxter Jul 26 '18 at 13:39

3 Answers3

2

are you sure you don't want to create a class to map it to as CodeCaster says?

public class Viagem 
{
    public int Id {get; set;}
    public string NumeroAtracacao {get; set;}
    public string Status {get; set;}
    public string Joint {get; set;}
    public string Servico {get; set;}
    public string MotivoEspera {get; set;}
    public Navio Navio {get; set;}
    public DateTime ChegadaPrevista {get; set;}
    public DateTime AtracacaoPrevista {get; set;}
    public DateTime SaidaPrevista {get; set;}
    public DateTime DeadLine {get; set;}
}

public class Navio 
{
    public string Nome {get; set;}
    public Armador Armador {get; set;}
    public string ImagemNavio {get; set;}
    public int Comprimento {get; set;}
    public int Lloyd {get; set;}
    public string CallSign {get; set;}
    public string CapacidadeTeus {get; set}
    public string Shortname {get; set;}
}

public class Armador 
{
    public int Id {get; set;}
    public object CodigoGeParcei {get; set;}
    public string Nome {get; set;}
    public string Sigla {get; set;}
    public object CnpjCpf {get; set;}
    public object Endereco {get; set;}
    public object Cep {get; set;}
    public object Site {get; set;}
}

you could then just do a straight

JsonConvert.DersializeObject<Viagem>(json); (if you're using Newtonsoft)

Dan Scott
  • 554
  • 3
  • 10
  • That is what I tried first, but the problem is when saving the information to database. So each of these classes will be a table right? But I will have to create relationship between all the classes and that is what is giving a lot of work. What would be the better way do save all the information to database. This way that you informed, really is the best way to deserialize, the only problem that I am facing is to save the information to DB. Thanks for the help. – Jairo Franchi Jul 26 '18 at 13:56
1

You should be able to use the JsonPathConverter class from Can I specify a path in an attribute to map a property in my class to a child property in my JSON? to do what you want.

To use it, first add a [JsonConverter] attribute to your Viagem class specifying the JsonPathConverter, like this:

[JsonConverter(typeof(JsonPathConverter))]
public partial class Viagem
{
    ...
}

Then, for each property that you want to deserialize from the JSON, add a [JsonProperty] attribute specifying its dot-separated path in the JSON. Here are a few examples:

    [JsonProperty("Viagem.Id")]
    public int Id { get; set; }

    [JsonProperty("Viagem.Status")]
    public string Status { get; set; }

    [JsonProperty("Viagem.Navio.Nome")]
    public string Navio_Nome { get; set; }

    [JsonProperty("Viagem.Navio.ImagemNavio")]
    public string ImagemNavio { get; set; }

    [JsonProperty("Viagem.Navio.Armador.Id")]
    public int? Armador_Id { get; set; }

    [JsonProperty("Viagem.Navio.Armador.Nome")]
    public string Armador_Nome { get; set; }

Then you can deserialize as you normally would, and it should "just work":

Viagem viagem = JsonConvert.DeserializeObject<Viagem>(json);

Here is a working demo: https://dotnetfiddle.net/repgUW

Note that if you need to serialize your model back to JSON, you will need to implement the WriteJson method in the converter. There is another answer in the linked question thread which suggests an implementation for that, but I have not tested it.

Brian Rogers
  • 125,747
  • 31
  • 299
  • 300
0

No, you don't want to map your JSON directly into a database entity class. You can go to great lengths and do some attribute and custom serializer logic, but that's a maintenance nightmare (what if the JSON or the entity's structure changes?).

Instead generate a class to deserialize this JSON into, and then map that class's fields to your entity.

CodeCaster
  • 147,647
  • 23
  • 218
  • 272