antipopp
antipopp

Reputation: 599

Rebuild JSON string to a different structure, parsing specific fields

I receive a JSON like this

{
   "raw_content":"very long string"
   "mode":"ML",
   "user_id":"4000008367",
   "user_description":"John Doe",
   "model":3,
   "dest_contact":"[email protected]",
   "order_details":[
      "ART.:  214883 PELL GRANI 9 ESPR.BAR SKGR 1000        SGOC.:  1000 GR\nVS.ART: 305920132                                     COMPOS. PALLET\n36  COLLI     PEZ.RA:      6  TOT.PEZZI:      216  B: 12  T:  6\nEU C.L.:   24,230\nCO  SCAP- :    16,500    CA  SCAP- :    15,000    CO  SCCP- :     0,000\nCO  SAGV- :     0,00000\nC.N. :    17,200SCAD.MIN.:    25/01/22\nCONDIZIONI PAGAMENTO : 60GG B.B. DT RIC FT FINEMESE ART62\n",
      "ART.:  287047 PELLINI BIO100%ARABICALTGR  250        SGOC.:   250 GR\nVS.ART: 315860176                                     COMPOS. PALLET\n36  COLLI     PEZ.RA:      6  TOT.PEZZI:      216  B: 12  T:  3\nEU C.L.:    8,380\nCO  SCAP- :    16,500    PR  SCAP- :    15,000    CO  SCCP- :     0,000\nCO  SAGV- :     0,00000\nC.N. :     5,950SCAD.MIN.:    25/01/22\nCONDIZIONI PAGAMENTO : 60GG B.B. DT RIC FT FINEMESE ART62\n",
      "ART.: 3137837 CAFFE PELLINI TOP     LTGR  250        SGOC.:   250 GR\nVS.ART: 315850175                                     COMPOS. PALLET\n30  COLLI     PEZ.RA:     12  TOT.PEZZI:      360  B:  6  T:  5\nEU C.L.:    6,810\nCO  SCAP- :    16,500    PR  SCAP- :    12,000    CO  SCCP- :     0,000\nCO  SAGV- :     0,00000\nC.N. :     5,000SCAD.MIN.:    18/08/21\nCONDIZIONI PAGAMENTO : 60GG B.B. DT RIC FT FINEMESE ART62\n",
      "ART.: 7748220 ESPRES.SUP.TRADIZ. MOKPKGR  500        SGOC.:   500 GR\nVS.ART: 315930114                                     COMPOS. PALLET\n80  COLLI     PEZ.RA:     10  TOT.PEZZI:      800  B: 10  T:  6\nEU C.L.:    7,580\nCO  SCAP- :    16,500    PR  SCAP- :    27,750    CO  SCCP- :     0,000\nCO  SAGV- :     0,00000\nC.N. :     4,570SCAD.MIN.:    25/01/22\nCONDIZIONI PAGAMENTO : 60GG B.B. DT RIC FT FINEMESE ART62\n"
   ],
   "order_footer":"\nPALLET DA CM. 80X120\nT O T A L E  C O L L I   182\n\n- EX D.P.R. 322 - 18/05/82 NON SI ACCETTANO TERMINI MINIMI DI\nCONSERVAZIONE INFERIORI A QUELLI INDICATI\n-      CONSEGNA FRANCO BANCHINA, PALLET MONOPRODOTTO\nCOME DA PALLETTIZZAZIONE SPECIFICATA\nCONDIZIONI DI PAGAMENTO : COME DA ACCORDI\n"
}

and I want to reorder it to this

{
    id: "32839ds8a32jjdas93193snkkk32jhds-k2j1", // generated, see my implementation
    rawContent: "very long string",
    parsedContent: {"mode":"ML", "user_id":"4000008367", "user_description":"John Doe", "order_details":[ "....." ], ... } // basically all the fields except raw content
}

How can I do this? I'm trying to work it with maps:

        var output map[string]interface{}
        var message processing.Document // message is of type struct {ID string, Raw string, Parsed string}

        err = json.Unmarshal([]byte(doc), &output)
        if err != nil {
            // error handling
        }

        message.ParsedContent = "{"

        for key, data := range output {
            if key == "raw_content" {
                hash := md5.Sum([]byte(data.(string)))
                message.ID = hex.EncodeToString(hash[:])
                message.RawContent = base64.RawStdEncoding.EncodeToString([]byte(data.(string)))
            } else {
                temp := fmt.Sprintf("\"%s\": \"%s\", ", key, data)
                message.ParsedContent = message.ParsedContent + temp
            }
        }

        message.ParsedContent = message.ParsedContent + "}"
        msg, err := json.Marshal(message)
        if err != nil {
            // error handling
        }

        fmt.Println(string(msg))

There's a few problem with this. If it was only strings it would be ok, but there are integers and the sprintf doesn't work (the output I get, for example on the field "model" is "model": "%!s(float64=3)". I could do an if key == model and parse it as an int, but as I said the fields are not always the same and there are other integers that sometimes are there and sometimes are not there. Also, the field "order_footer" has escaped new lines which are somehow deleted in my parsing, and this breaks the validity of the resulting JSON.

How can I solve this issues?

EDIT: As suggested, hand-parsing JSON is a bad idea. I could parse it into a struct, the field "model" actually tells me which struct to use. The struct for "model": 3 for example is:

type MOD3 struct {
    Raw                     string   `json:"raw_content"`
    Mode                    string   `json:"mode"`
    UserID                  string   `json:"user_id"`
    UserDes                 string   `json:"user_description"`
    Model                   int      `json:"model"`
    Heading                 string   `json:"legal_heading"`
    DestContact             string   `json:"dest_contact"`
    VendorID                string   `json:"vendor_id"`
    VendorLegal             string   `json:"vendor_legal"`
    OrderID                 string   `json:"order_id"`
    OrderDate               int64    `json:"order_date"`
    OrderReference          string   `json:"order_reference"`
    DeliveryDate            int64    `json:"delivery_date"`
    OrderDestination        string   `json:"order_destination"`
    OrderDestinationAddress string   `json:"order_destination_address"`
    Items                   []string `json:"order_details"`
    OrderFooter             string   `json:"order_footer"`
}

At this point, how can I parse specific fields to the output format?

Upvotes: 0

Views: 33

Answers (1)

gnasher729
gnasher729

Reputation: 52538

You should never, ever, ever try to generate JSON by hand. The steps should be:

  1. Get JSON and parse it in a model object.
  2. Create a copy of the model object with all the changes you want.
  3. Convert the copied model object to JSON.

You don't know enough about JSON to modify it on the fly. I know enough, and the only reasonable way is complete parsing, and writing back the complete changes.

Upvotes: 1

Related Questions