<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: leofigy</title>
    <description>The latest articles on DEV Community by leofigy (@leofigy).</description>
    <link>https://dev.to/leofigy</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F235283%2F14277cb1-3e6c-42d7-ac2a-c6cf36518bd5.jpeg</url>
      <title>DEV Community: leofigy</title>
      <link>https://dev.to/leofigy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/leofigy"/>
    <language>en</language>
    <item>
      <title>Inconsistent json unmarshal </title>
      <dc:creator>leofigy</dc:creator>
      <pubDate>Tue, 24 Sep 2019 03:23:14 +0000</pubDate>
      <link>https://dev.to/leofigy/inconsistent-json-unmarshal-37m1</link>
      <guid>https://dev.to/leofigy/inconsistent-json-unmarshal-37m1</guid>
      <description>&lt;h1&gt;
  
  
  Common daily task
&lt;/h1&gt;

&lt;p&gt;Go provides has a json package in the standard library. However a common case we face everyday at work is that our input is not consistent, that means a json entry could have different data types. &lt;/p&gt;

&lt;p&gt;Consider the following input jsons&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# good input
{
    "name": "Sam smith",
    "age" : 34
}
# lazy input 
{
    "name": "Sam smith stringer",
    "age" : "41"
}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;as one can see the "age" field has two different types string and number.&lt;br&gt;
Go provides a trick to handle this case; So the recipe is&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Write your go struct with the right types&lt;/li&gt;
&lt;li&gt;Create an Alias for your struct to avoid recursively unmarshal &lt;/li&gt;
&lt;li&gt;Unmarshal to your intermediate struct with your embbeded alias&lt;/li&gt;
&lt;li&gt;Select the attributes of your struct and parse them to the intended type &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Full code snippet
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package main

import (
    "fmt"
    "encoding/json"
    "strconv"
)

type InputJSON struct {
    Name string `json:"name,omitempty"`
    Age  int    `json:"age,omitempty"`
}

/* Alias to avoid calling implicit UnmarshalJSON of your original 
   struct 
*/
type Alias InputJSON

/* write your Unmarshal function using an intermediate struct to use interface to handle any type */
func (i *InputJSON) UnmarshalJSON(input []byte) error {
    // intermediate step
    middle := struct {
        Alias 
        Age interface{} `json:"age,omitempty"`
    }{}

    if err := json.Unmarshal(input, &amp;amp;middle); err != nil {
        return err
    }

    *i = InputJSON(middle.Alias)

    if middle.Age != nil {
        switch realValue := (middle.Age).(type) {
        case string:
            intValue, err := strconv.Atoi(realValue)
            if err != nil {
                return err
            }
            i.Age = intValue
        case float64:
            // by default uses a float64 for number representation
            i.Age = int(realValue)
        }
    }
    return nil
}

func main() {
    // use cases 
    expectedCase := []byte(`
        {
            "name": "Sam smith",
            "age" : 34
        }
    `)

    awfulCase := []byte(`
        {
            "name": "Sam smith stringer",
            "age" : "41"
        }
    `)

    goodInput := InputJSON{}

    if err := json.Unmarshal(expectedCase, &amp;amp;goodInput); err != nil {
        fmt.Println(err)
    }
    fmt.Printf("%+v\n", goodInput)

    badInput := InputJSON{}

    if err := json.Unmarshal(awfulCase, &amp;amp;badInput); err != nil {
        fmt.Println(err)
    }
    fmt.Printf("%+v\n", badInput)

}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Not the most elegant way to do it, but it works :) &lt;/p&gt;

&lt;p&gt;&lt;a href="https://play.golang.org/p/dwAPmGtHzZi"&gt;https://play.golang.org/p/dwAPmGtHzZi&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>json</category>
      <category>unmarshal</category>
    </item>
  </channel>
</rss>
