Cela a commencé comme une simple publication dans un groupe Slack interne. Ensuite, on m’a demandé de le publier sur une autre chaîne de ce Slack. Ensuite, j’ai décidé de le publier sur Slack DevRel Collective. À ce stade, on m’a demandé d’en faire un article de blog pour qu’il ne se perde pas dans le défilement arrière (DevRel Collective utilise un compte Slack gratuit, nous ne pouvons donc faire défiler que 10 000 messages. Avec plus de 2000 membres, cela se produit plus rapidement que vous ne le pensez. Mais je m’éloigne du sujet.)

Pourquoi ces outils

Je faisbeaucoup de développement dans Go. Je n’ai vraiment jamais pensé que je le ferais, mais si vous avez lu ceci ou this ou this vous verrez que j’ai été sucé (Une autre brève digression. Oui, j’ai entendu parler de Rust. C’est la prochaine langue sur ma liste. Donnez-moi une minute.)

Le go est devenu mon langage de prédilection car je sais maintenant comment y faire rapidement des choses. Il est également facile d’exécuter plusieurs plates-formes pour que je puisse développer sur mon Mac et déployer sur Linux et cela fonctionne Just Works ™.

Dans la plupart de mes travaux avec Go, je traite des données dans json et des fichiers de configuration dans yaml ou toml la plupart du temps, donc trouver des outils pour faciliter le traitement de ces données est toujours le bienvenu!

Il y a un outil bonus à la fin, si vous lisez le tout.

JSON d’abord

En traitant avec JSON, dans Go, il y a 3 choses communes que je dois faire tout le temps:

  • Valider le JSON
  • Démarrez un objet JSON dans une structure Go
  • Accéder à un champ particulier dans un objet JSON

Valider JSON

La validation du JSON n’est pas toujours obligatoire, mais c’est généralement une bonne idée. Rien de plus frustrant que d’essayer de traiter un objet JSON uniquement pour découvrir que ce que vous essayez de gérer n’est pas vraiment JSON approprié.

Je valide donc d’abord le JSON en utilisant jasonlint. Collez votre objet json et il vous dira immédiatement si ce que vous avez entre les mains est, en fait, un objet JSON valide.

Démarquer un objet JSON

Go propose des méthodes pratiques pour gérer les objets JSON, ce qui en fait mon outil de prédilection pour les données JSON. Si vous recevez un objet JSON, par exemple en interrogeant un site Web pour obtenir des données via une API, vous pouvez utiliser


  err := json.Unmarshal(data, &myStruct)

Et les données seront supprimées dans votre structure de données. Mais, et c’est un gros mais, vous devez avoir une structure de données qui correspond exactement à vos données entrantes.

Et c’est là que json-to-go entre en jeu. Prenez votre objet JSON validé, collez-le sur le côté gauche et hors de droite côté vient une structure de données Go valide pour le tenir.


  {
    "name": "David",
    "ParentEmailAddress": "spam@davidgs.com",
    "letter": "I want a pony",
    "address": {
      "home": "Not your business where I live",
      "work": "Also probably none of your business, but Camunda"
    }
  }

Je l’ai exécuté via le linter JSON, et c’est valide. Génial. Maintenant, une structure Go pour le tenir:


  type Autogenerated struct {
    Name               string `json:"name"`
    Parentemailaddress string `json:"ParentEmailAddress"`
    Letter             string `json:"letter"`
    Address            struct {
      Home string `json:"home"`
      Work string `json:"work"`
    } `json:"address"`
  }

Et maintenant, je peux écrire du code Go:


  import (
    "encoding/json"
    "log"
  )
  myStruct = Autogenerated{}
  data := getJsonData()
  err := json.Unmarshal(data, &myStruct)
  if err != nil {
    log.Fatal(err)
  }

Et myStruct sera une structure de données correctement remplie avec les données de mon objet JSON entrant.

Ce qui m’amène à la troisième chose que je fais: accéder à des champs spécifiques d’un objet JSON.

Accéder à un champ particulier d’un objet JSON

Avec notre structure JSON simple ci-dessus, cela ne serait pas un problème difficile pour la plupart. Vous voulez l’adresse de travail?


  work_address = jsonObject.address.work

et vous y êtes. Mais que se passe-t-il si votre objet JSON est extrêmement compliqué?


  {
    "status": "OK",
    "results": [
      {
        "geometry": {
          "location": {
            "lat": 37.4229181,
            "lng": -122.0854212
          },
          "viewport": {
            "northeast": {
              "lat": 37.4242670803,
              "lng": -122.08407222
            },
            "southwest": {
              "lat": 37.4215691197,
              "lng": -122.08677018
            }
          },
          "location_type": "ROOFTOP"
        },
        "address_components": [
          {
            "long_name": "1600",
            "short_name": "1600",
            "types": [
              "street_number"
            ]
          },
          {
            "long_name": "Amphitheatre Pkwy",
            "short_name": "Amphitheatre Pkwy",
            "types": [
              "route"
            ]
          },
          {
            "long_name": "Mountain View",
            "short_name": "Mountain View",
            "types": [
              "locality",
              "political"
            ]
          },
          {
            "long_name": "Santa Clara",
            "short_name": "Santa Clara",
            "types": [
              "administrative_area_level_2",
              "political"
            ]
          },
          {
            "long_name": "California",
            "short_name": "CA",
            "types": [
              "administrative_area_level_1",
              "political"
            ]
          },
          {
            "long_name": "United States",
            "short_name": "US",
            "types": [
              "country",
              "political"
            ]
          },
          {
            "long_name": "94043",
            "short_name": "94043",
            "types": [
              "postal_code"
            ]
          }
        ],
        "formatted_address": "1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA",
        "types": [
          "street_address"
        ]
      }
    ]
}

Et ce n’est même pas complexe par rapport à certains avec lesquels je traite régulièrement, mais pour l’argumentation, disons que c’est le cas. Et disons que vous voulez extraire le deuxième type du address_component qui, dans l’exemple ci-dessus, est la ville, “Mountain View”. Eh bien, le results est en fait un tableau, bien que dans l’exemple ci-dessus, il ne contienne qu’un seul élément. Si le tableau contenait beaucoup d’éléments et que vous vouliez le résultat du troisième élément du tableau, cela devient un peu plus difficile.

C’est là que json selector entre en jeu. Collez votre objet JSON (dont nous savons déjà qu’il est valide, car vous l’avez validé,droit?) Et cliquez simplement sur quoi vous voulez.


['results'][0]['address_components'][2]['types'][1]

Oh mon Dieu! Il y a! C’est le premier élément du tableau results, c’est le champ address_components, et le troisième élément dansthat tableau, et c’est le deuxième élément du tableau types!

Rappelez-vous, la numérotation des tableaux commence à zéro!

Un ensemble d’outils complet

Et c’est un ensemble d’outils complet pour traiter les objets JSON. Mais attendez, j’ai mentionné yaml et je n’en ai pas encore parlé!

Corriger! Et merci pour votre attention!

YAML

YAML: Encore un autre langage de balisage. Parce que ce dont le monde a besoin, c’est de plus de langages de balisage. Mais yaml est super utile pour les fichiers de configuration. J’utilise des fichiers de configuration basés sur yaml pour toutes sortes de choses. Le fichier de configuration pour la construction de tout ce site Web est un fichier yaml.

Il est donc important de pouvoir analyser et traiter correctement un fichier yaml.

Encore une fois, avec Go, c’est relativement simple. Mon premier outil est yaml2go. Tout comme json-to-go, il prendra votre structure de fichier yaml et la transformera en structures de données Go.


  # Paste your yaml here...
  kind: test
  metadata:
    name: cluster
    namespace: test-ns

And get yourself some spiffy Go code:

// MyYaml
type MyYaml struct {
  Kind     string   `yaml:"kind"`
  Metadata Metadata `yaml:"metadata"`
}

// Metadata
type Metadata struct {
  Name      string `yaml:"name"`
  Namespace string `yaml:"namespace"`
}

Et puis vous pouvez démarshall votre fichier de configuration:


  import (
    "io/ioutil"
    "log"
    "gopkg.in/yaml.v2"
  )
  var config MyYaml
  // InitConfig reads the config file and sets up the config struct
  func InitConfig(){
    dat, err := ioutil.ReadFile("./config.yaml")
    if err != nil {
      log.Fatal("No startup file: ", err)
    }
    err = yaml.Unmarshal(dat, &config)
    if err != nil {
      log.Fatal(err)
    }
  }

Et traitez vos variables de configuration à partir de là. Lorsque vous avez terminé, si vous voulez écrire votre fichier config.yaml (vous savez, si votre programme en cours a changé des paramètres de démarrage), vous pouvez tout écrire après l’avoir rassemblé:


  import (
    "io/ioutil"
    "log"
    "gopkg.in/yaml.v2"
  )
  // WriteDictators outputs the entire config file
  func WriteConfig() {
    newConf, err := yaml.Marshal(config)
    if err != nil {
      log.Fatal(err)
    }
    err = ioutil.WriteFile("./config.yaml", newConf, 0644)
    if err != nil {
      panic(err)
    }
  }

Vous avez maintenant écrasé votre ancien fichier de configuration par votre nouveau fichier de configuration. C’est essentiellement la même chose que JSON, juste pour yaml.

Temps d’outil bonus!

Celui-ci a sauvé mon bacon à plus d’une occasion. Parce que je suis vraiment, ** vraiment * nul à écrire des expressions régulières (RegEx). Comme vraiment. Je suis terrible. Tellement terrible que jusqu’à ce que je trouve ce tooll, j’écrirais 30 lignes de code Go à environ un seul appel à une regex.

Pas. Quelconque. Suite!

Entrez RegEx101. Je ne peux même pas commencer à dire à quel point cet outil est brillant. Laissez-moi expliquer.

Vous pouvez (ou non) remarquer que ce site Web est traduit dans plusieurs langues. Je ne parle d’aucune d’elles. Je n’en écris aucun. Mais j’écris Go. Ainsi, en utilisant Go et les API de traduction de Google, je peux traduire automatiquement n’importe quel article ici dans la ou les langues de mon choix.

Mais l’API de traduction fait des choses sérieusement gâchées avec des parties d’un fichier Markdown. J’ai donc dû compenser. Les URL sont un excellent exemple. Si mon fichier blog-post.md contient un lien[mon lien](https://my.link)alors Google Traduction traduira avec plaisir[mon lien], ce que je veux, puis ajoutez un espace entre ] (, ce que je ne veux pas, et ensuite (parfois) traduire les composants du chemin du lien, ce que je ne veux pas ** définitivement.

J’ai donc dû compenser, comme je l’ai dit. Au début, je l’ai fait manuellement, et c’était un vrai gâchis. Il était sujet aux erreurs et difficile à maintenir. Mais ensuite j’ai trouvé RexEx101 et tout a changé.

Je pourrais faire ceci: Une expression régulière qui trouve l’url dans le paragraphe ci-dessus

Et puis cela explique même ce que font les parties varoius de la regex!

explication des parties de la correspondance regex

Ainsi, je peux faire en sorte que mon programme Go trouve toutes les URL dans un morceau de texte donné, puis une fois le texte traduit, remplacez tous les ](original/url) par ] (original / url)


  // fix URLs because google translate changes [link](http://your.link) to
  // [link] (http://your.link) and it *also* will translate any path
  // components, thus breaking your URLs.
  reg := regexp.MustCompile(`]\([-a-zA-Z0-9@:%._\+~#=\/]{1,256}\)`)
  // get all the URLs with a single RegEx, keep them for later.
  var foundUrls [][]byte = reg.FindAll([]byte(xlate), -1)
  ...
  // translate the bit
  // Now it's time to go back and replace all the fucked up urls ...
  reg = regexp.MustCompile(`] \([-a-zA-Z0-9@:%._\+~#=\/ ]{1,256}\)`)
  for x := 0; x < len(foundUrls); x++ {
    tmp := reg.FindIndex([]byte(translated))
    if tmp == nil {
      break
    }
    t := []byte(translated)
    translated = fmt.Sprintf("%s(%s%s", string(t[0:tmp[0]+1]), string(foundUrls[x][2:]), (string(t[tmp[1]:])))
  }

Je pourrais également l’utiliser pour trouver l’autre extrémité: regex pour trouver les URL en désordre

Et il explique toujours utilement ce qu’il fait:

explication de la façon dont l&rsquo;expression régulière correspond à diverses parties du texte d&rsquo;entrée

Oh mon! Je pourrais également corriger les autres choses que Google Trnaslate gâche, comme bold text ** bold ** devient ** bold ** qui n’est plus gras. Mais avec ça:


// a bunch of regexs to fix other broken stuff
	reg = regexp.MustCompile(` (\*\*) ([A-za-z0-9]+) (\*\*)`) // fix bolds (**foo**)
	translated = string(reg.ReplaceAll([]byte(translated), []byte(" $1$2$3")))
	reg = regexp.MustCompile(`&quot;`) // fix escaped quotes
	translated = string(reg.ReplaceAll([]byte(translated), []byte("\"")))
	reg = regexp.MustCompile(`&gt;`) //fix >
	translated = string(reg.ReplaceAll([]byte(translated), []byte(">")))
	reg = regexp.MustCompile(`&lt;`) // fix <
	translated = string(reg.ReplaceAll([]byte(translated), []byte("<")))
	reg = regexp.MustCompile(`&#39;`) // fix '
	translated = string(reg.ReplaceAll([]byte(translated), []byte("'")))
	reg = regexp.MustCompile(` (\*) ([A-za-z0-9]+) (\*)`) // fix underline (*foo*)
	translated = string(reg.ReplaceAll([]byte(translated), []byte("$1$2$3")))

Brilliant. Becaues I never would have been able to write those Regular Expressions without serious help!

Conclusion

I hope you found these tools as helpful as I do. I really do use them on a near-daily basis for the work I do. I have them pinned as tabs in my browser so they are always open and easy to find.

If you know of other tools, please do let me know! And don’t forget to follow me on Twitter!