Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 11
  1. #1

    Elaborare json senza saperne la struttura

    ciao!

    sono sempre stato abituato a fare il parsing dei json sapendone la struttura a priori.
    però, ho questa cosa che vorrei fare:
    • ho un web service che espone parecchie risorse in formato json
    • ma ogni risorsa ha un formato diverso dall'altro (ad esempio un'estrazione di clienti è differente da una estrazioni di articoli)
    • io vorrei crearmi un piccolo programma che dato in input il json, lo trasformi in excel, in moda da distribuirlo più facilmente ai colleghi


    come creare un file excel in java lo so, quello che mi manca è come fare il parsing del json in maiera dinamica, senza sapere a priori come è fatto.
    è possibile?
    avete qualche suggerimento??

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,254
    Quote Originariamente inviata da fermat Visualizza il messaggio
    ma ogni risorsa ha un formato diverso dall'altro (ad esempio un'estrazione di clienti è differente da una estrazioni di articoli)
    io vorrei crearmi un piccolo programma che dato in input il json, lo trasformi in excel, in moda da distribuirlo più facilmente ai colleghi

    quello che mi manca è come fare il parsing del json in maiera dinamica, senza sapere a priori come è fatto.
    è possibile?
    Immagino che vuoi fare una soluzione "generalizzata", per evitare di dover definire N (svariate) classi per il binding. Perché anche in questo caso, nessuno vieterebbe di applicare il data binding. Anche se sono svariate risorse, ciascuna ha un suo formato ben preciso ... non credo che cambi per caso .. così .. dall'oggi al domani.

    Se l'obiettivo però è quello di ottenere come risultato una "griglia" di dati, bisogna vedere come è la struttura del JSON. Deve essere molto lineare e ben strutturata. Non può avere particolarità, sottorami extra o cose del genere .... altrimenti come estrai le cose?

    Spiego meglio, se la struttura del JSON fosse:

    codice:
    un array
        N oggetti, tutti con lo stesso formato
            M campi

    Questo è quanto di più vicino ad una tabella, o "griglia" di dati.

    Comunque bisogna anche vedere quale libreria JSON intendi usare. La ben nota Jackson offre ben 3 modalità di parsing:
    - la Streaming API, a basso livello. Ovvero estrai tu i "token" uno dopo l'altro e devi dedurre tu se si tratta di un campo String, un numero, l'inizio di un array, ecc..
    - Il Tree Model, ovvero Jackson ti fornisce una rappresentazione ad "albero" in memoria di tutto il JSON e puoi "navigarci" dentro tu come vuoi.
    - Il Data Binding che permette la mappatura tra il JSON e classi Java "bean".
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    Java Versions Cheat Sheet

  3. #3
    ciao andbin!

    si volevo generalizzare la cosa per vari motivi.
    primo fra tutti: se aggiungo un altro WS, che estrae altre risorse ancora (ad esempio le fatture, che una estrazione diversa sia da clienti che da articoli) vorrei che il programma sia cmq in grado di farne il parsing e creare l'excel.
    senza dover aggiungere un'altra classe al programma per il binding, ricompilarlo, ecc.
    (non so se mi sono spiegato bene).

    quindi, per fare ciò, mi consigli Jackson.
    suppongo usando una delle due prime modalità (perchè la terza presuppone la creazione di java bean che corrispondano alla struttura del json).
    corretto??

  4. #4
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,254
    Quote Originariamente inviata da fermat Visualizza il messaggio
    quindi, per fare ciò, mi consigli Jackson.
    Anche la Gson offre un approccio in streaming, sebbene sia sicuramente più limitato rispetto alla Jackson.

    Quote Originariamente inviata da fermat Visualizza il messaggio
    suppongo usando una delle due prime modalità (perchè la terza presuppone la creazione di java bean che corrispondano alla struttura del json).
    Dipende anche dalla dimensione del JSON. Se usi il Tree Model della Jackson, hai TUTTA la struttura del JSON in memoria. E se è grande .....

    Quindi inizia magari a vedere l'approccio in streaming. Comunque, ribadisco, bisogna vedere come è la struttura del JSON, se è facilmente "tabellizzabile" oppure no.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    Java Versions Cheat Sheet

  5. #5
    ti posto due esempi (semplificati), che fanno interrogazioni diverse su db, e che quindi estraggono i dati in "formati" diversi.

    esempio clienti:
    codice:
    [{
        "codiceCliente": 00000,
        "ragSoc": ".......",
        "partIva": "......",
        "codFiscale": "......",
        "indirizzo": "......
        "telefono": "......."
    }, {
        "codiceCliente": 00000,
        "ragSoc": ".......",
        "partIva": "......",
        "codFiscale": "......",
        "indirizzo": "......
        "telefono": "......."
        "telefono": "952213840"
    }]
    dove qui c'è un campo intero (il codice) e tutti gli atri stringa.

    qui gli articoli:
    codice:
    [{
        "codice": "....",
        "modello": "......",
        "colore": ".....",
        "taglia": "....."
    }, {
        "codice": "....",
        "modello": "......",
        "colore": ".....",
        "taglia": "....."
    }]
    qui invece sono tutti stringa.

    i dati li prendo tramite un programma sul server che usa JAX-RS.

  6. #6
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,254
    Quote Originariamente inviata da fermat Visualizza il messaggio
    ti posto due esempi (semplificati)
    Per i JSON che hai postato, sì, sono perfettamente trattabili come "tabella". Sono tutti oggetti uniformi e ciascuno rappresenterà una riga nel tuo excel.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    Java Versions Cheat Sheet

  7. #7
    allora, mi sono copiato una parte del json per fare una prova.
    è così composto:
    codice:
    [{
        "npu": 1,
        "npuAgenda": 0,
        "codiceCliente": 000000,
        "codiceTmp": 000,
        "tipoConto": "CLMT",
        "ragSoc": ".............",
        "breve": "............",
        "partIva": "................",
        "codFiscale": "....................",
        "via": "................",
        "localita": "..............",
        "cap": "...............",
        "provincia": null,
        "nazione": "...",
        "ie": "........",
        "telefono": "..........."
    },
    .......................................
    ]
    ci stanno 6 "record" nel file.
    ho scritto questo codice:
    codice:
        public static void main(String[] args) {
            try {
                String filePath = "/home/matte/Desktop/clienti.json";
                File file = new File(filePath);
                JsonFactory jf = new JsonFactory();
                try (JsonParser parser = jf.createParser(file)) {
                    while (parser.nextToken() != JsonToken.END_OBJECT) {
                        String fieldName = parser.getCurrentName();
                        Object fieldValue = parser.getCurrentValue();
                        if (fieldName != null) {
                            System.out.println(fieldName + " - " + fieldValue);
                        }
                    }
                }
            } catch (IOException ex) {
                System.out.println(ex.getMessage());
            }
        }
    l'output è questo:
    codice:
    npu - null
    npu - null
    npuAgenda - null
    npuAgenda - null
    codiceCliente - null
    codiceCliente - null
    codiceTmp - null
    codiceTmp - null
    tipoConto - null
    tipoConto - null
    ragSoc - null
    ragSoc - null
    breve - null
    breve - null
    partIva - null
    partIva - null
    codFiscale - null
    codFiscale - null
    via - null
    via - null
    localita - null
    localita - null
    cap - null
    cap - null
    provincia - null
    provincia - null
    nazione - null
    nazione - null
    ie - null
    ie - null
    telefono - null
    c'è qualcosa che non va....
    ma non riesco a capire dove sto sbagliando!!

  8. #8
    allora, c'è qualcosa che nn mi quadra proprio.
    ho modifcato il file json, riducendolo ad un solo "record":
    codice:
    [{
        "npu": 1,
        "npuAgenda": 0,
        "codiceCliente": 000000,
        "codiceTmp": 000,
        "tipoConto": "CLMT",
        "ragSoc": ".............",
        "breve": "............",
        "partIva": "................",
        "codFiscale": "....................",
        "via": "................",
        "localita": "..............",
        "cap": "...............",
        "provincia": null,
        "nazione": "...",
        "ie": "........",
        "telefono": "..........."
    }]
    poi, ho modificato anche il codice vedendo un pò di esempi online:
    codice:
    public class Main {
    
        public static void main(String[] args) {
            try {
                String filePath = "/home/matte/Desktop/clienti.json";
                File file = new File(filePath);
                JsonFactory jf = new JsonFactory();
                try (JsonParser parser = jf.createParser(file)) {
                    while (parser.nextToken() != JsonToken.END_OBJECT) {
                        JsonToken jt = parser.getCurrentToken();
                        if (jt != JsonToken.START_ARRAY) {
                            String fieldName = parser.getCurrentName();
                            Object fieldValue = parser.getCurrentValue();
                            System.out.println(fieldName + " - " + fieldValue);
                        }
                    }
                }
            } catch (IOException ex) {
                System.out.println(ex.getMessage());
            }
        }
    }
    il risultato però è praticamente lo stesso:
    codice:
    null - null
    npu - null
    npu - null
    npuAgenda - null
    npuAgenda - null
    codiceCliente - null
    codiceCliente - null
    codiceTmp - null
    codiceTmp - null
    tipoConto - null
    tipoConto - null
    ragSoc - null
    ragSoc - null
    breve - null
    breve - null
    partIva - null
    partIva - null
    codFiscale - null
    codFiscale - null
    via - null
    via - null
    localita - null
    localita - null
    cap - null
    cap - null
    provincia - null
    provincia - null
    nazione - null
    nazione - null
    ie - null
    ie - null
    telefono - null
    telefono - null

  9. #9
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,254
    Quello che hai scritto non va granché bene, anche perché è troppo "blando" e non particolarmente "robusto".

    Questo è quello che si potrebbe fare:

    codice:
    import java.io.IOException;
    
    import com.fasterxml.jackson.core.JsonFactory;
    import com.fasterxml.jackson.core.JsonParseException;
    import com.fasterxml.jackson.core.JsonParser;
    import com.fasterxml.jackson.core.JsonToken;
    
    public class LetturaJsonTabulare {
        private JsonFactory factory;
        private JsonParser parser;
    
        public LetturaJsonTabulare(String json) throws JsonParseException, IOException {
            factory = new JsonFactory();
            parser = factory.createParser(json);
        }
    
        public void close() throws IOException {
            parser.close();
        }
    
        public void parse() throws IOException {
            JsonToken token;
    
            while ((token = parser.nextToken()) != null) {
                if (token == JsonToken.START_ARRAY) {
                    parseMainArray();
                } else {
                    throw new IllegalStateException("Token is not the start of array as expected");
                }
            }
        }
    
        private void parseMainArray() throws IOException {
            JsonToken token;
    
            while ((token = parser.nextToken()) != JsonToken.END_ARRAY) {
                if (token == JsonToken.START_OBJECT) {
                    parseMainArrayObject();
                } else {
                    throw new IllegalStateException("Token is not the start of object as expected");
                }
            }
        }
    
        private void parseMainArrayObject() throws IOException {
            System.out.println("Inizio oggetto");
            JsonToken token;
    
            while ((token = parser.nextToken()) != JsonToken.END_OBJECT) {
                if (token != JsonToken.FIELD_NAME) {
                    throw new IllegalStateException("Token is not a field name as expected");
                }
    
                String fieldName = parser.getText();
    
                token = parser.nextToken();
    
                switch (token) {
                case VALUE_STRING:
                    System.out.printf("   %s = %s (String)%n", fieldName, parser.getValueAsString());
                    break;
                case VALUE_NUMBER_INT:
                    System.out.printf("   %s = %d (int)%n", fieldName, parser.getValueAsInt());
                    break;
                /* gestire eventualmente altri tipi ... */
                default:
                    throw new IllegalStateException("Token is not an handled value type");
                }
            }
        }
    
    
        public static void main(String[] args) {
            String json =
                    "[{" +
                    "   \"nome\": \"Mario\"," +
                    "   \"cognome\": \"Rossi\"," +
                    "   \"annoNascita\": 1956" +
                    "}, {" +
                    "   \"nome\": \"Roberto\"," +
                    "   \"cognome\": \"Verdi\"," +
                    "   \"annoNascita\": 1983" +
                    "}]";
    
            try {
                LetturaJsonTabulare lettura = new LetturaJsonTabulare(json);
    
                try {
                    lettura.parse();
                } finally {
                    lettura.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    Nota come l'analisi del JSON "discende" nei vari metodi parse/parseMainArray/parseMainArrayObject man mano che si discende appunto nella struttura del JSON.

    Ma con tutti i check fatti è anche estremamente robusto. Se il primo token non è l'inizio di un array (es. se fosse l'inizio di un oggetto), lo sto considerando un errore. Se nell'array principale trovo altro che non è un object, lo sto considerando un errore.
    Ecc...
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    Java Versions Cheat Sheet

  10. #10
    decisamente mi sfuggiva qualcosa......
    adesso ho capito meglio come funziona questa libreria.
    ho dovuto solo aggiungere il VALUE_NULL.

    grazie mille!!!!

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.