Browse Source

Added LoadJson to autostruct

  * LoadJson currently supports 'simple.json' (maps, arrays must be all
the same type, todo is to make it support various types thus switching
to a separate sub-struct)
  * We have example2.go generated from main2.go (this example shows how
LoadJson can process a json file to produce the structure following it)
  * Need to update README to clarify autostruct's weaknesses.
Apollo 2 years ago
parent
commit
08293ef2f0
4 changed files with 143 additions and 8 deletions
  1. 67 8
      autostruct.go
  2. 12 0
      examples/example2.go
  3. 29 0
      examples/main2.go
  4. 35 0
      examples/simple.json

+ 67 - 8
autostruct.go

@@ -1,8 +1,12 @@
 package autostruct
 
 import (
+	"encoding/json"
 	"fmt"
+	"log"
 	"os"
+	"reflect"
+	"strings"
 )
 
 // Generates structures given json
@@ -15,19 +19,20 @@ type AutoStruct struct {
 	File        *os.File // Access to the new go file (writer)
 }
 
+// Sets up the AutoStruct to build a go file containing structures
 //
+// Structname is a prefix to add to all structures, if no prefix desired leave an empty string in place
 func (a *AutoStruct) Init(fname, packname, structname string) error {
 	a.StructName = structname
 	a.FileName = fname
 	a.PackageName = packname
-	if !FileExists(a.FileName + ".go") {
-		var err error
-		a.File, err = os.Create(a.FileName + ".go")
-		if err != nil {
-			return err
-		}
-	} else {
-		return fmt.Errorf("file already exists, update mode is not yet implemented")
+	var err error
+	if FileExists(a.FileName + ".go") {
+		log.Printf("AutoStruct.Init('%s', '%s', '%s') => Warning, file exists, this is an experimental feature.", fname, packname, structname)
+	}
+	a.File, err = os.OpenFile(a.FileName+".go", os.O_CREATE|os.O_RDWR, 0666)
+	if err != nil {
+		return err
 	}
 	return nil
 }
@@ -145,3 +150,57 @@ func (a *AutoStruct) Comment(comment string) {
 func (a *AutoStruct) Close() {
 	a.File.Close()
 }
+
+// Forms needed structures and a master structure
+//
+// TODO: Change it so it actually forms a map[string]string key=fieldname value=fieldtype
+//       This will allow us to then form other structures we need as we iterate the data
+func (a *AutoStruct) LoadJson(filename, structname string) (int, error) {
+	var structsMade int
+	var err error
+	var file []byte
+	file, err = os.ReadFile(filename + ".json")
+	if err != nil {
+		return structsMade, err
+	}
+	var data map[string]interface{}
+	err = json.Unmarshal(file, &data)
+	if err != nil {
+		return structsMade, err
+	}
+	fmt.Printf("%#v\n", data)
+	// Wrong, we actually want to store this then make any substructures then make the base struct
+	a.StartStruct(structname)
+	for k, v := range data {
+		k = strings.ReplaceAll(k, "-", "_") // Replace '-' with '_'
+		k = strings.ReplaceAll(k, " ", "")  // Remove ' '
+		switch reflect.TypeOf(v).Kind() {
+		case reflect.Array, reflect.Slice:
+			// Array or slice []
+			// Check all types are the same (else need new struct)
+			// Iterate over nested array/slice and maps
+
+			// Assuming all types are same
+			var array []interface{} = v.([]interface{})
+			a.AddField(k, "[]"+reflect.TypeOf(array[0]).String())
+		case reflect.Map:
+			// Map key, val
+			// Check all types are the same (else need new struct)
+			// Iterate over nested array/slice and maps
+
+			// Assuming all types are same
+			var mp map[string]interface{} = v.(map[string]interface{})
+			var keys []string = make([]string, 0, len(mp))
+			for k2 := range mp {
+				keys = append(keys, k2)
+			}
+			a.AddField(k, "map[string]"+reflect.TypeOf(mp[keys[0]]).String())
+		default:
+			// Fallback
+			a.AddField(k, reflect.TypeOf(v).String())
+		}
+	}
+	structsMade += 1
+	a.EndStruct()
+	return structsMade, nil
+}

+ 12 - 0
examples/example2.go

@@ -0,0 +1,12 @@
+package main
+
+// simple.json
+type SimpleStruct struct {
+	programming_languages []string
+	test string
+	ships []float64
+	numbers []float64
+	mapofstuff map[string][]interface {}
+	name string
+	age float64
+}

+ 29 - 0
examples/main2.go

@@ -0,0 +1,29 @@
+package main
+
+import (
+	"fmt"
+
+	"red-green.com/autostruct"
+)
+
+func main() {
+	// This example will load a json file in & produce a go file with needed structures out
+	var a autostruct.AutoStruct
+	var err error
+	err = a.Init("simple", "main", "Simple") // This will make a simple.go file
+	if err != nil {
+		fmt.Println(err)
+	} else {
+		defer a.Close()
+		a.PlacePackageName()
+		a.Newline()
+		a.Comment("simple.json") // the file we will be loading in is 'simple.json'
+		var structCount int
+		structCount, err = a.LoadJson("simple", "")
+		if err != nil {
+			fmt.Println(err)
+		} else {
+			fmt.Printf("%d Structures created\n", structCount)
+		}
+	}
+}

+ 35 - 0
examples/simple.json

@@ -0,0 +1,35 @@
+{
+    "name": "Apollo",
+    "age": 23,
+    "programming-languages": [
+        "python",
+        "go",
+        "c++",
+        "lua"
+    ],
+    "test": "24.01",
+    "ships": [
+        3,
+        54,
+        7,
+        9
+    ],
+    "numbers": [
+        3.14156,
+        0.98,
+        42
+    ],
+    "map of stuff": {
+        "ships": [
+            3,
+            54,
+            7,
+            9
+        ],
+        "numbers": [
+            3.14156,
+            0.98,
+            42
+        ]
+    }
+}