PDA

Visualizza la versione completa : Deserializzare Json da API


djciko
22-09-2020, 22:43
Ciao, ho un metodo di un'API che restituisce un array di oggetti.

Questa la chiamata in POST al metodo:



WebClient client = new WebClient();

Classe dati_input = new Classe();

client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
byte[] byteArray = Encoding.ASCII.GetBytes(dati_input);


byte[] responseArray = client.UploadData(uriString, "POST", byteArray);
string dati_temp = Encoding.ASCII.GetString(responseArray);


ClasseOutput classe_output = JsonConvert.DeserializeObject<ClasseOutput>(dati_temp); <<--- PROBLEMA




Ora, l'oggetto <classe_output> non riesce ad essere valorizzato dalla serializzazione.


Il JSON che viene restituito dalla chiamata :


{
"IFAGE00201": {
"UTERET_profilo_rete_comm": "IFAGE00201",
"DTAIAR_data_da": "20180101",
"DTAFAR_data_a": "20491231",
"QALRET_qualifica_rete": "COL",
"CDCLAR_cod_controparte": "AGE002",
"ndg_cdclar": "",
"RASOC_ragione_sociale": "AGENTE SPECIAL FASCIA 1",
"FILARE_filiale": "01",
"CDLIAR_cod_controp_liquid": "AGE002",
"ndg_cdliar": "",
"UTPDAR_utente_padre": "IFIFI00101",
"ndg_utpdar": "",
"GRURET_gruppo_appartenenza": "",
"AIREC_abilitato_caricamento": "S",
"ACFRE_abilitato_caricamento_figli": "",
"dataRif": "20201010",
"XCDRES_responsabile": "AP",
"listaProdottiAbilit": "C2,CA,CB,CC,CF,CH,CI,CN,DA,DB,DC,DH,DI,FI,PE,PN,PR ,PS,PT,PU",
"obbligoFinanziato": ""
}
}



E' un array di oggetti.

Domanda: perch il metodo DeserializeObject non riesce a deserializzarlo ?
Dice che il formato del json non valido.

Ho provato anche con un array di stringhe (string[]) ma niente, non capisce il JSON.
Devo eliminare qualche parentesi o metterci quelle quadre ?


Ho provato anche:

List<ClasseOutput> classe_output = JsonConvert.DeserializeObject<List<ClasseOutput>>(dati_temp);

ma nulla.

U235
23-09-2020, 02:06
Ciao djciko,
Forse non ho ben capito io, ma il json restituito non ne una classe con un tipo singolo e ne un array, per cui mi venuto il dubbio che il problema possa essere li, quindi sarebbe necessario controllare anche la classe che usi per de-serializzare.
Dovrebbe essere una cosa del genere :


public class Rootobject
{
public IFAGE00201 IFAGE00201 { get; set; }
}


public class IFAGE00201
{
public string UTERET_profilo_rete_comm { get; set; }
public string DTAIAR_data_da { get; set; }
public string DTAFAR_data_a { get; set; }
public string QALRET_qualifica_rete { get; set; }
public string CDCLAR_cod_controparte { get; set; }
public string ndg_cdclar { get; set; }
public string RASOC_ragione_sociale { get; set; }
public string FILARE_filiale { get; set; }
public string CDLIAR_cod_controp_liquid { get; set; }
public string ndg_cdliar { get; set; }
public string UTPDAR_utente_padre { get; set; }
public string ndg_utpdar { get; set; }
public string GRURET_gruppo_appartenenza { get; set; }
public string AIREC_abilitato_caricamento { get; set; }
public string ACFRE_abilitato_caricamento_figli { get; set; }
public string dataRif { get; set; }
public string XCDRES_responsabile { get; set; }
public string listaProdottiAbilit { get; set; }
public string obbligoFinanziato { get; set; }
}

Quindi ad essere de-serializzata dovrebbe essere la class rootobject secondo l'esempio sopra, e nel caso sia un array di rootobject (non ho capito, magari intendevi quello) devi utilizzare un List<rootobject>


JsonConvert.DeserializeObject<List<rootobject>>


Il quel caso il json dovrebbe essere dentro le quadre:


[{
"IFAGE00201": {
"UTERET_profilo_rete_comm": "IFAGE00201",
"DTAIAR_data_da": "20180101",
"DTAFAR_data_a": "20491231",
"QALRET_qualifica_rete": "COL",
"CDCLAR_cod_controparte": "AGE002",
"ndg_cdclar": "",
"RASOC_ragione_sociale": "AGENTE SPECIAL FASCIA 1",
"FILARE_filiale": "01",
"CDLIAR_cod_controp_liquid": "AGE002",
"ndg_cdliar": "",
"UTPDAR_utente_padre": "IFIFI00101",
"ndg_utpdar": "",
"GRURET_gruppo_appartenenza": "",
"AIREC_abilitato_caricamento": "S",
"ACFRE_abilitato_caricamento_figli": "",
"dataRif": "20201010",
"XCDRES_responsabile": "AP",
"listaProdottiAbilit": "C2,CA,CB,CC,CF,CH,CI,CN,DA,DB,DC,DH,DI,FI,PE,PN,PR ,PS,PT,PU",
"obbligoFinanziato": ""
},
{
"IFAGE00201": {
"UTERET_profilo_rete_comm": "IFAGE00201",
"DTAIAR_data_da": "20180101",
"DTAFAR_data_a": "20491231",
"QALRET_qualifica_rete": "COL",
"CDCLAR_cod_controparte": "AGE002",
"ndg_cdclar": "",
"RASOC_ragione_sociale": "AGENTE SPECIAL FASCIA 1",
"FILARE_filiale": "01",
"CDLIAR_cod_controp_liquid": "AGE002",
"ndg_cdliar": "",
"UTPDAR_utente_padre": "IFIFI00101",
"ndg_utpdar": "",
"GRURET_gruppo_appartenenza": "",
"AIREC_abilitato_caricamento": "S",
"ACFRE_abilitato_caricamento_figli": "",
"dataRif": "20201010",
"XCDRES_responsabile": "AP",
"listaProdottiAbilit": "C2,CA,CB,CC,CF,CH,CI,CN,DA,DB,DC,DH,DI,FI,PE,PN,PR ,PS,PT,PU",
"obbligoFinanziato": ""
}
}]

Ma sempre meglio restituire un oggetto che dentro contiene una propriet come array

U235
23-09-2020, 15:32
Siccome il mio post precedente non risulta visibile provo ad aggiungere un post.

ciao

djciko
23-09-2020, 16:27
il post e' visibile.


Semplicemente, il JSON rappresenta un array di persone, ma strano.
Stavo usando le classi:




public class containerRamiRete
{
public out_ramoRete ramo { get; set; }
}


public class out_ramoRete
{
public IList<nodoRete> listaAgenti { get; set; }
}


public class nodoRete
{
public string UTERET_profilo_rete_comm { get; set; }
public string DTAIAR_data_da { get; set; }
public string DTAFAR_data_a { get; set; }
public string QALRET_qualifica_rete { get; set; }
public string CDCLAR_cod_controparte { get; set; }
public string ndg_cdclar { get; set; }
public string RASOC_ragione_sociale { get; set; }
public string FILARE_filiale { get; set; }
public string CDLIAR_cod_controp_liquid { get; set; }
public string ndg_cdliar { get; set; }
public string UTPDAR_utente_padre { get; set; }
public string ndg_utpdar { get; set; }
public string GRURET_gruppo_appartenenza { get; set; }
public string AIREC_abilitato_caricamento { get; set; }
public string ACFRE_abilitato_caricamento_figli { get; set; }
public string dataRif { get; set; }
public string XCDRES_responsabile { get; set; }
public string listaProdottiAbilit { get; set; } // [CA”,”CB”,”DA”] // prodotti abilitati
public string obbligoFinanziato { get; set; }
}



ma alle istruzioni:




// PROVA 1 -----------------------------------------------------------------------------------------
// aaaa contiente un oggetto di tipo <out_ramoRete> = NULL

List<out_ramoRete> nodo1 = JsonConvert.DeserializeObject<List<out_ramoRete>>(dati);



// PROVA 2 -----------------------------------------------------------------
//Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[ApiClient2.nodoRete]' 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<T>) 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 'IFAGE00201', line 1, position 14.'


List<nodoRete> nodo2 = JsonConvert.DeserializeObject<List<nodoRete>>(dati);





....Restituiva gli errori che ho riportato commentati sopra l'istruzione.


Poi, grazie a StackOverflow, ho incontrato: https://json2csharp.com :unz: e l'ho fatto funzionare.

Vedo che il tuo esempio preso da li' (ero da 3 giorni e sono contemporaneamente arrivato alla soluzione).

Ho solo alcuni dubbi, poi li chiariro' con la software house che ha sviluppato le API.

Grazie.





Ah, un'altra istruzione funzionava, provala:



// restituisce un Newtonsoft.Json.Linq.JObject
dynamic ramoreteOut = JsonConvert.DeserializeObject(dati);



ma non sapevo maneggiare l'oggetto di ritorno (Newtonsoft.Json.Linq.JObject ??)

U235
23-09-2020, 16:59
il post e' visibile.



Io lo vedevo solo entrando dentro il post, ma non risultava nemmeno come ultimo messaggio, ne nella lista degli ultimi messaggi finch non ho aggiunto il secondo post. Questo sia dopo che l'ho scritto stanotte sia fino a poco fa. Poi non so



Semplicemente, il JSON rappresenta un array di persone, ma strano.
Stavo usando le classi:




public class containerRamiRete
{
public out_ramoRete ramo { get; set; }
}


public class out_ramoRete
{
public IList<nodoRete> listaAgenti { get; set; }
}


public class nodoRete
{
public string UTERET_profilo_rete_comm { get; set; }
public string DTAIAR_data_da { get; set; }
public string DTAFAR_data_a { get; set; }
public string QALRET_qualifica_rete { get; set; }
public string CDCLAR_cod_controparte { get; set; }
public string ndg_cdclar { get; set; }
public string RASOC_ragione_sociale { get; set; }
public string FILARE_filiale { get; set; }
public string CDLIAR_cod_controp_liquid { get; set; }
public string ndg_cdliar { get; set; }
public string UTPDAR_utente_padre { get; set; }
public string ndg_utpdar { get; set; }
public string GRURET_gruppo_appartenenza { get; set; }
public string AIREC_abilitato_caricamento { get; set; }
public string ACFRE_abilitato_caricamento_figli { get; set; }
public string dataRif { get; set; }
public string XCDRES_responsabile { get; set; }
public string listaProdottiAbilit { get; set; } // [CA,CB,DA] // prodotti abilitati
public string obbligoFinanziato { get; set; }
}



ma alle istruzioni:




// PROVA 1 -----------------------------------------------------------------------------------------
// aaaa contiente un oggetto di tipo <out_ramoRete> = NULL

List<out_ramoRete> nodo1 = JsonConvert.DeserializeObject<List<out_ramoRete>>(dati);



// PROVA 2 -----------------------------------------------------------------
//Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[ApiClient2.nodoRete]' 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<T>) 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 'IFAGE00201', line 1, position 14.'


List<nodoRete> nodo2 = JsonConvert.DeserializeObject<List<nodoRete>>(dati);





....Restituiva gli errori che ho riportato commentati sopra l'istruzione.

Ma quel json che hai postato non strutturato in questo modo...



Poi, grazie a StackOverflow, ho incontrato: https://json2csharp.com :unz: e l'ho fatto funzionare.

Vedo che il tuo esempio preso da li' (ero da 3 giorni e sono contemporaneamente arrivato alla soluzione).

Ho solo alcuni dubbi, poi li chiariro' con la software house che ha sviluppato le API.

Grazie.



No, non un esempio preso da li, ma semplicemente quando vuoi ricreare una classe da un json in maniera abbastanza precisa sufficiente copiare negli appunti il json e dopo da visualstudio apri il menu modifica e scegli incolla speciale->incolla json come classi.
Niente di complicato o esterno e sei sicuro che hai le classi corrette per quel json.



Ah, un'altra istruzione funzionava, provala:



// restituisce un Newtonsoft.Json.Linq.JObject
dynamic ramoreteOut = JsonConvert.DeserializeObject(dati);



ma non sapevo maneggiare l'oggetto di ritorno (Newtonsoft.Json.Linq.JObject ??)

un dynamic, quindi semplicemente chiami i suoi membri dopo il punto come un qualsiasi oggetto tenendo presente in compilazione non da errori (e ovviamente visual studio non da suggerimenti), ma se il nome del membro della classe non esiste dar un errore in runtime.

U235
23-09-2020, 17:17
30060
Anche ora (prima di postare questo presumo) vedo quello nell'immagine allegata.


EDIT: ora con questo altro post lo vedo.

P.S.
ok l'immagine piccola e non si vede molto... pardon, ma fidati c' scritto che l'ultimo messaggio il tuo.
Lo vedo solo io cos?

djciko
23-09-2020, 17:28
non lo so, avendo postato un'altra cosa ora si vede il tuo nome anche da fuori.


prova a postare qualcosa con codice, senza post successivo.

(dopo aver capito questo problema del forum ti rispondo al quesito tecnico del post)

U235
23-09-2020, 17:32
non lo so, avendo postato un'altra cosa ora si vede il tuo nome anche da fuori.


prova a postare qualcosa con codice, senza post successivo.

(dopo aver capito questo problema del forum ti rispondo al quesito tecnico del post)

Ricreo tutto, quindi anche il quote.



if(siVede)
FammiSapere;
else
FammiSapereComunque;

djciko
23-09-2020, 18:45
si vede :D

djciko
24-09-2020, 11:23
Ma quel json che hai postato non strutturato in questo modo...

il json questo:


{
"IFAGE00201": {
"UTERET_profilo_rete_comm": "IFAGE00201",
"DTAIAR_data_da": "20180101",
"DTAFAR_data_a": "20491231",
"QALRET_qualifica_rete": "COL",
"CDCLAR_cod_controparte": "AGE002",
"ndg_cdclar": "",
"RASOC_ragione_sociale": "AGENTE SPECIAL FASCIA 1",
"FILARE_filiale": "01",
"CDLIAR_cod_controp_liquid": "AGE002",
"ndg_cdliar": "",
"UTPDAR_utente_padre": "IFIFI00101",
"ndg_utpdar": "",
"GRURET_gruppo_appartenenza": "",
"AIREC_abilitato_caricamento": "S",
"ACFRE_abilitato_caricamento_figli": "",
"dataRif": "20201010",
"XCDRES_responsabile": "AP",
"listaProdottiAbilit": "C2,CA,CB,CC,CF,CH,CI,CN,DA,DB,DC,DH,DI,FI,PE,PN,PR ,PS,PT,PU",
"obbligoFinanziato": ""
}
}


cha intendi ?

Loading