-
Notifications
You must be signed in to change notification settings - Fork 3
/
json2csv.go
138 lines (124 loc) · 3.26 KB
/
json2csv.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package main
import (
"encoding/csv"
"encoding/json"
"fmt"
"os"
"strings"
)
type BitwardenLogin struct {
Username string `json:"username"`
Password string `json:"password"`
TOTP string `json:"totp"`
URLs []struct {
URL string `json:"uri"`
} `json:"uris"`
}
type BitwardenCard struct {
CardholderName string `json:"cardholderName"`
Brand string `json:"brand"`
Number string `json:"number"`
ExpiryMonth string `json:"expMonth"`
ExpiryYear string `json:"expYear"`
Cvv string `json:"code"`
}
type BitwardenItem struct {
Name string `json:"name"`
Type int `json:"type"`
Login BitwardenLogin `json:"login"`
Card BitwardenCard `json:"card"`
Notes string `json:"notes"`
}
type BitwardenExport struct {
Items []BitwardenItem `json:"items"`
}
func main() {
// Check if the correct number of arguments is provided
if len(os.Args) != 2 {
fmt.Println("Usage: go run json2csv.go <jsonFilePath>")
return
}
jsonFilePath := os.Args[1]
csvFilePath := strings.Replace(jsonFilePath, ".json", ".csv", 1)
// Read the JSON file
jsonData, err := os.ReadFile(jsonFilePath)
if err != nil {
fmt.Println("Error reading JSON file:", err)
return
}
// Unmarshal the JSON data into a slice of BitwardenItem
var bwExport BitwardenExport
err = json.Unmarshal(jsonData, &bwExport)
if err != nil {
fmt.Println("Error unmarshaling json: ", err)
return
}
// Create a new CSV file
csvFile, err := os.Create(csvFilePath)
if err != nil {
fmt.Println("Error creating CSV file:", err)
return
}
defer csvFile.Close()
// Initialize the CSV writer
csvWriter := csv.NewWriter(csvFile)
defer csvWriter.Flush()
// Write the header row to the CSV file
header := []string{"Group", "Name", "Username", "Password", "URL", "Notes", "TOTP"}
err = csvWriter.Write(header)
if err != nil {
fmt.Println("Error writing CSV header:", err)
return
}
// Write each Bitwarden item to the CSV file
for _, item := range bwExport.Items {
// Export secure notes
if item.Type == 2 {
row := []string{"Secure Note", item.Name, "", "", "", item.Notes, ""}
err = csvWriter.Write(row)
if err != nil {
fmt.Println("Error writing CSV row:", err)
return
}
} else if item.Type == 3 {
// Export credit/debit cards, store everything in notes column
row := []string{
"Card",
item.Name,
"",
"",
"",
"Cardholder Name: " + item.Card.CardholderName + "\n" +
"Brand: " + item.Card.Brand + "\n" +
"Number: " + item.Card.Number + "\n" +
"Expiry: " + item.Card.ExpiryMonth + "-" + item.Card.ExpiryYear + "\n" +
"CVV: " + item.Card.Cvv + "\n\n\n" + item.Notes,
"",
}
err = csvWriter.Write(row)
if err != nil {
fmt.Println("Error writing CSV row:", err)
return
}
} else {
// In Bitwarden, an item can have multiple URLs, so we'll write each URL as a separate row
for _, url := range item.Login.URLs {
row := []string{
"Website Login",
item.Name,
item.Login.Username,
item.Login.Password,
url.URL,
item.Notes,
item.Login.TOTP,
}
err = csvWriter.Write(row)
if err != nil {
fmt.Println("Error writing CSV row:", err)
return
}
}
}
}
fmt.Println("Filtered data has been written to", csvFilePath)
}