├── .github └── workflows │ └── go-release-build.yml ├── .gitignore ├── .goreleaser.yml ├── LICENSE ├── README.e.md ├── README.md ├── cmd_esc.go ├── cmd_fmt.go ├── cmd_j2s.go ├── cmd_sort.go ├── cmd_x2j.go ├── go.mod ├── go.sum ├── imp_esc.go ├── imp_fmt.go ├── imp_j2s.go ├── imp_sort.go ├── imp_x2j.go ├── jsonfiddle_cli.yaml ├── jsonfiddle_cliDef.go ├── jsonfiddle_cliGen.sh ├── jsonfiddle_main.go ├── jsonfiddle_test.go └── test ├── Books.ref ├── Books.xml ├── Customer.json ├── Customer.ref ├── CustomerC.ref ├── CustomerJ2S.ref ├── CustomerP.json ├── CustomerP.ref ├── CustomerPC.ref ├── CustomerPS.ref ├── CustomerSC.ref ├── CustomerSI.ref ├── Goods.json ├── GoodsJ2S.ref ├── MenuItems.json ├── MenuItemsJ2S.ref ├── Schedules.json ├── Schedules.ref ├── SchedulesJ2S.ref ├── SchedulesSI.ref ├── SmartyStreets.json ├── SmartyStreetsCLK.json ├── SmartyStreetsCUC.json ├── SmartyStreetsJ2S.ref └── friendfeed_oww.json /.github/workflows/go-release-build.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | env: 4 | GO111MODULE: off 5 | 6 | on: 7 | push: 8 | branches: 9 | - 'master' 10 | tags: 11 | - 'v*' 12 | 13 | # Allows you to run this workflow manually from the Actions tab 14 | workflow_dispatch: 15 | 16 | jobs: 17 | build: 18 | runs-on: ubuntu-latest 19 | steps: 20 | - 21 | name: Set up Go 22 | uses: actions/setup-go@v2 23 | with: 24 | go-version: 1.17 25 | 26 | - 27 | name: Checkout 28 | uses: actions/checkout@v2 29 | with: 30 | fetch-depth: 0 31 | 32 | - 33 | name: Tests 34 | run: | 35 | export GOPATH=/home/runner/go 36 | mkdir -vp $GOPATH/src/github.com/$GITHUB_REPOSITORY 37 | rmdir -v $GOPATH/src/github.com/$GITHUB_REPOSITORY 38 | mv -v $GITHUB_WORKSPACE $GOPATH/src/github.com/$GITHUB_REPOSITORY 39 | ln -vs $GOPATH/src/github.com/$GITHUB_REPOSITORY $GITHUB_WORKSPACE 40 | # go mod tidy 41 | go get -v ./... 42 | go build -v 43 | go test -v ./... 44 | 45 | - 46 | name: Run GoReleaser 47 | uses: goreleaser/goreleaser-action@v2 48 | if: success() && startsWith(github.ref, 'refs/tags/') 49 | with: 50 | version: latest 51 | args: release --rm-dist 52 | env: 53 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 54 | 55 | - 56 | name: Install Cloudsmith CLI 57 | if: success() && startsWith(github.ref, 'refs/tags/') 58 | run: pip install --upgrade cloudsmith-cli 59 | # Cloudsmith CLI tooling for pushing releases 60 | # See https://help.cloudsmith.io/docs/cli 61 | 62 | # Publish to cloudsmith repo 63 | - 64 | name: Publish package to cloudsmith 65 | if: success() && startsWith(github.ref, 'refs/tags/') 66 | env: 67 | CLOUDSMITH_API_KEY: ${{ secrets.CLOUDSMITH_API_KEY }} 68 | run: | 69 | for filepath in dist/*; do 70 | echo "== Analyzing '$filepath' for publishing" 71 | filename=$(basename -- "$filepath") 72 | extension="${filename##*.}" 73 | filename="${filename%.*}" 74 | case "$extension" in 75 | 'apk') 76 | echo "Pushing '$filepath' to cloudsmith repo" 77 | cloudsmith push alpine suntong/repo/alpine/any-version $filepath 78 | ;; 79 | 'deb' | 'rpm') 80 | echo "Pushing '$filepath' to cloudsmith repo" 81 | cloudsmith push $extension suntong/repo/any-distro/any-version $filepath 82 | ;; 83 | *) 84 | echo "File .$extension skipped publishing" 85 | echo 86 | ;; 87 | esac 88 | done 89 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.dll 4 | *.so 5 | *.dylib 6 | 7 | # Test binary, build with `go test -c` 8 | *.test 9 | 10 | # Output of the go coverage tool, specifically when used with LiteIDE 11 | *.out 12 | 13 | # Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 14 | .glide/ 15 | jsonfiddle 16 | jsonfiddle.exe 17 | test/*.got 18 | -------------------------------------------------------------------------------- /.goreleaser.yml: -------------------------------------------------------------------------------- 1 | project_name: jsonfiddle 2 | 3 | archives: 4 | - format: tar.gz 5 | wrap_in_directory: true 6 | format_overrides: 7 | - goos: windows 8 | format: zip 9 | # remove README and LICENSE 10 | files: 11 | - none* 12 | 13 | builds: 14 | - env: [CGO_ENABLED=0] 15 | goos: 16 | - linux 17 | - windows 18 | - darwin 19 | goarch: 20 | - amd64 21 | - arm64 22 | 23 | # Path to main.go file or main package. 24 | # Default is `.`. 25 | 26 | nfpms: 27 | - maintainer: Tong Sun 28 | description: jsonfiddle - Tool to fiddle with json strings 29 | homepage: https://github.com/go-jsonfiddle/jsonfiddle 30 | license: MIT 31 | formats: 32 | - deb 33 | - rpm 34 | - apk 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 go-jsonfile 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.e.md: -------------------------------------------------------------------------------- 1 | 2 | # {{.Name}} 3 | 4 | {{render "license/shields" . "License" "MIT"}} 5 | {{template "badge/godoc" .}} 6 | {{template "badge/goreport" .}} 7 | {{template "badge/travis" .}} 8 | [![PoweredBy WireFrame](https://github.com/go-easygen/wireframe/blob/master/PoweredBy-WireFrame-R.svg)](http://godoc.org/github.com/go-easygen/wireframe) 9 | 10 | ## {{toc 5}} 11 | 12 | ## {{.Name}} - JSON Fiddling 13 | 14 | The `jsonfiddle` makes it easy to look at the JSON data from different aspects. 15 | 16 | - **`jsonfiddle esc`** will escape any arbitrary string so as to embed it as content of json string. 17 | - **`jsonfiddle fmt`** will format the JSON data, either compact it or pretty printing it. The order of fields are intact. 18 | - **`jsonfiddle sort`** will sort the JSON data fields recursively, so that the attributes at any level are in sorted order. 19 | - **`jsonfiddle x2j`** means xml to json. It will convert data from xml format into json. 20 | - **`jsonfiddle j2s`** means json to struct. It will extract the structure of JSON data as Go struct. 21 | 22 | # Usage 23 | 24 | ``` 25 | $ {{shell "jsonfiddle -V"}} 26 | ``` 27 | 28 | ### $ {{shell "jsonfiddle || true" | color "sh"}} 29 | 30 | ### $ {{shell "jsonfiddle esc || true" | color "sh"}} 31 | 32 | ### $ {{shell "jsonfiddle fmt || true" | color "sh"}} 33 | 34 | ### $ {{shell "jsonfiddle sort || true" | color "sh"}} 35 | 36 | ### $ {{shell "jsonfiddle j2s || true" | color "sh"}} 37 | 38 | ### $ {{shell "jsonfiddle x2j || true" | color "sh"}} 39 | 40 | # Examples 41 | 42 | ## Escape with `jsonfiddle esc` 43 | 44 | ### $ {{shell "jsonfiddle esc -i test/Customer.ref 2>/dev/null" | color "json"}} 45 | 46 | ### Usage 47 | 48 | `jsonfiddle esc` will escape any arbitrary string so as to embed it as content of json string. This seems useless at first, but it actually allows you to embed any arbitrary file into [GitHub Gists JSON API](https://developer.github.com/v3/gists/), so as to post any arbitrary file onto GitHub Gist: 49 | 50 | 51 | echo '{"description":"SmartyStreets API Demo","public":true,"files":{"SmartyStreets.json":{"content":'"`jsonfiddle fmt -i test/SmartyStreets.json | jsonfiddle esc -i`"'}}}' | curl --data @- https://api.github.com/gists 52 | 53 | This will give you 54 | https://gist.github.com/anonymous/1423d4768dd9b88262ca513626e68d8e 55 | 56 | 57 | By "_arbitrary file_" I do mean arbitrary file. Check this out: 58 | https://gist.github.com/anonymous/a51798ce99ff59d8d4ba536cbf4b6996 59 | 60 | This is why `jsonfiddle esc` is a command on its own, instead of being part of functionalities of `jsonfiddle fmt` or `jsonfiddle sort`. 61 | 62 | ## Format with `jsonfiddle fmt` 63 | 64 | ### Pretty print 65 | 66 | $ jsonfiddle fmt -i test/Customer.json 67 | 68 | #### > {{cat "test/CustomerSI.ref" | color "json"}} 69 | 70 | ### Protect templates in json data 71 | 72 | There are times that json data may contain templates, i.e., strings like `{{"{{VARIABLE}}"}}`. Some of the pretty printing tools, like the json plugin in Notepad++, cannot handle such template forms well, and will turn `{{"{{VARIABLE}}"}}` into: 73 | 74 | ```json 75 | { 76 | { 77 | VARIABLE 78 | } 79 | } 80 | ``` 81 | 82 | What's worse is that when such template variables are for `int`, e.g.: `"age":{{"{{Var_Age}}"}}`, they then wouldn't be able to handle it, for inputs like 83 | {{cat "test/CustomerP.json" | color "sh"}} 84 | 85 | To make such template variables work for those tools, the `-p,--protect` option is introduced: 86 | 87 | $ jsonfiddle fmt -p -i test/CustomerP.json 88 | 89 | #### > {{cat "test/CustomerP.ref" | color "json"}} 90 | 91 | ### Compact 92 | 93 | $ jsonfiddle fmt -c -i test/Customer.json 94 | 95 | #### > {{cat "test/CustomerC.ref" | color "json"}} 96 | 97 | You can also do, 98 | 99 | $ cat Customer.json | jsonfiddle fmt -c -i - 100 | 101 | and the result is the same (and for all other examples using `-i` as well). 102 | 103 | ## Sort fields with `jsonfiddle sort` 104 | 105 | ### Sort in compact 106 | 107 | $ jsonfiddle sort -c -i test/Customer.json 108 | 109 | #### > {{cat "test/CustomerSC.ref" | color "json"}} 110 | 111 | ### Sort with pretty print 112 | 113 | $ jsonfiddle sort -i test/Customer.json 114 | 115 | #### > {{cat "test/CustomerSI.ref" | color "json"}} 116 | 117 | ### XML to JSON, sort then pretty print 118 | 119 | ``` 120 | $ {{shell "jsonfiddle x2j -i test/Books.xml | jsonfiddle sort -i - | jsonfiddle fmt -i -"}} 121 | ``` 122 | 123 | ## JSON to struct via `jsonfiddle j2s` 124 | 125 | $ jsonfiddle j2s -i test/Customer.json 126 | 127 | #### > {{cat "test/CustomerJ2S.ref" | color "go"}} 128 | 129 | 130 | # Purpose 131 | 132 | A few more words on why I'm writing the tool -- because I need to compare JSON string that are roughly close and very complicated in the mean time -- sometimes even less than 30% of fields are the same, of course, this is after their having been sorted, otherwise, it'd be 100% different. 133 | 134 | Thus all the JSON comparison tools I found are failing under such hash request. So far, I personally find that 135 | 136 | - Sorting the JSON data fields recursively and producing plain text file (via `jsonfiddle sort`), then use the state-of-the-art text comparison tools to compare them is the best approach, for my above scenario. 137 | - For extremely long and very complicated JSONs, converting json to abstract Go struct (via `jsonfiddle j2s`) is the quickest approach to compare them at higher level. 138 | 139 | # Download binaries 140 | 141 | - The latest binary executables are available under 142 | https://github.com/go-jsonfile/{{.Name}}/releases 143 | as the result of the Continuous-Integration process. 144 | - I.e., they are built right from the source code during every git tagging commit automatically. 145 | - Pick & choose the binary executable that suits your OS and its architecture. E.g., for Linux, it would most probably be the `{{.Name}}_linux_VER_amd64` file. If your OS and its architecture is not available in the download list, please let me know and I'll add it. 146 | - You may want to rename it to a shorter name instead, e.g., `{{.Name}}`, after downloading it. 147 | 148 | 149 | # Debian package 150 | 151 | Available at the above releases url as well. 152 | 153 | # Install Source 154 | 155 | To install the source code instead: 156 | 157 | ``` 158 | go get github.com/go-jsonfile/jsonfiddle 159 | ``` 160 | 161 | 162 | ## Credits 163 | 164 | - [Ladicle/gojson](https://github.com/Ladicle/gojson) forked source for JSON to struct 165 | - [ChimeraCoder/gojson](https://github.com/ChimeraCoder/gojson) the original source of [Ladicle/gojson](https://github.com/Ladicle/gojson). 166 | 167 | ## Similar Projects 168 | 169 | All the following similar projects have been considered before writing one on my own instead. 170 | 171 | . . . to be filled . . . 172 | 173 | ## Author(s) & Contributor(s) 174 | 175 | Tong SUN 176 | ![suntong from cpan.org](https://img.shields.io/badge/suntong-%40cpan.org-lightgrey.svg "suntong from cpan.org") 177 | 178 | _Powered by_ [**WireFrame**](https://github.com/go-easygen/wireframe), [![PoweredBy WireFrame](https://github.com/go-easygen/wireframe/blob/master/PoweredBy-WireFrame-Y.svg)](http://godoc.org/github.com/go-easygen/wireframe), the _one-stop wire-framing solution_ for Go cli based projects, from start to deploy. 179 | 180 | All patches welcome. 181 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # jsonfiddle 3 | 4 | [![MIT License](http://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) 5 | [![GoDoc](https://godoc.org/github.com/go-jsonfile/jsonfiddle?status.svg)](http://godoc.org/github.com/go-jsonfile/jsonfiddle) 6 | [![Go Report Card](https://goreportcard.com/badge/github.com/go-jsonfile/jsonfiddle)](https://goreportcard.com/report/github.com/go-jsonfile/jsonfiddle) 7 | [![travis Status](https://travis-ci.org/go-jsonfile/jsonfiddle.svg?branch=master)](https://travis-ci.org/go-jsonfile/jsonfiddle) 8 | [![PoweredBy WireFrame](https://github.com/go-easygen/wireframe/blob/master/PoweredBy-WireFrame-R.svg)](http://godoc.org/github.com/go-easygen/wireframe) 9 | 10 | ## TOC 11 | - [jsonfiddle - JSON Fiddling](#jsonfiddle---json-fiddling) 12 | - [Usage](#usage) 13 | - [$ jsonfiddle || true](#-jsonfiddle--true) 14 | - [$ jsonfiddle esc || true](#-jsonfiddle-esc--true) 15 | - [$ jsonfiddle sort || true](#-jsonfiddle-sort--true) 16 | - [$ jsonfiddle x2j || true](#-jsonfiddle-x2j--true) 17 | 18 | ## jsonfiddle - JSON Fiddling 19 | 20 | The `jsonfiddle` makes it easy to look at the JSON data from different aspects. 21 | 22 | - **`jsonfiddle esc`** will escape any arbitrary string so as to embed it as content of json string. 23 | - **`jsonfiddle fmt`** will format the JSON data, either compact it or pretty printing it. The order of fields are intact. 24 | - **`jsonfiddle sort`** will sort the JSON data fields recursively, so that the attributes at any level are in sorted order. 25 | - **`jsonfiddle x2j`** means xml to json. It will convert data from xml format into json. 26 | - **`jsonfiddle j2s`** means json to struct. It will extract the structure of JSON data as Go struct. 27 | 28 | # Usage 29 | 30 | ``` 31 | $ jsonfiddle -V 32 | jsonfiddle - JSON Fiddling, version 0.5.0 33 | Built on 2023-01-22 34 | Copyright (C) 2017-2023, Tong Sun 35 | 36 | Tool to fiddle with json strings 37 | ``` 38 | 39 | ### $ jsonfiddle || true 40 | ```sh 41 | Please specify one command of: esc, fmt, j2s, sort or x2j 42 | 43 | Usage: 44 | jsonfiddle [OPTIONS] 45 | 46 | Application Options: 47 | -c, --compact Compact JSON data, remove all whitespaces 48 | --prefix= prefix for json string output 49 | -d, --indent= indent for json string output (default: ) 50 | -p, --protect protect {{TEMPLATE}} in JSON data 51 | -v, --verbose Verbose mode (Multiple -v options increase the verbosity) 52 | -V, --version Show program version and exit 53 | 54 | Help Options: 55 | -h, --help Show this help message 56 | 57 | Available commands: 58 | esc Escape json string 59 | fmt Format json string 60 | j2s JSON to struct 61 | sort Sort json fields recursively 62 | x2j XML to JSON 63 | ``` 64 | 65 | ### $ jsonfiddle esc || true 66 | ```sh 67 | the required flag `-i, --input' was not specified 68 | 69 | Usage: 70 | jsonfiddle [OPTIONS] esc [esc-OPTIONS] 71 | 72 | Application Options: 73 | -c, --compact Compact JSON data, remove all whitespaces 74 | --prefix= prefix for json string output 75 | -d, --indent= indent for json string output (default: ) 76 | -p, --protect protect {{TEMPLATE}} in JSON data 77 | -v, --verbose Verbose mode (Multiple -v options increase the verbosity) 78 | -V, --version Show program version and exit 79 | 80 | Help Options: 81 | -h, --help Show this help message 82 | 83 | [esc command options] 84 | -i, --input= the source to get json string from (or "-" for stdin) 85 | (mandatory) 86 | -o, --output= the output, default to stdout (default: -) 87 | ``` 88 | 89 | ### $ jsonfiddle fmt || true 90 | ```sh 91 | the required flag `-i, --input' was not specified 92 | 93 | Usage: 94 | jsonfiddle [OPTIONS] fmt [fmt-OPTIONS] 95 | 96 | Application Options: 97 | -c, --compact Compact JSON data, remove all whitespaces 98 | --prefix= prefix for json string output 99 | -d, --indent= indent for json string output (default: ) 100 | -p, --protect protect {{TEMPLATE}} in JSON data 101 | -v, --verbose Verbose mode (Multiple -v options increase the verbosity) 102 | -V, --version Show program version and exit 103 | 104 | Help Options: 105 | -h, --help Show this help message 106 | 107 | [fmt command options] 108 | -i, --input= the source to get json string from (mandatory) 109 | -o, --output= the output, default to stdout (default: -) 110 | ``` 111 | 112 | ### $ jsonfiddle sort || true 113 | ```sh 114 | the required flag `-i, --input' was not specified 115 | 116 | Usage: 117 | jsonfiddle [OPTIONS] sort [sort-OPTIONS] 118 | 119 | Application Options: 120 | -c, --compact Compact JSON data, remove all whitespaces 121 | --prefix= prefix for json string output 122 | -d, --indent= indent for json string output (default: ) 123 | -p, --protect protect {{TEMPLATE}} in JSON data 124 | -v, --verbose Verbose mode (Multiple -v options increase the verbosity) 125 | -V, --version Show program version and exit 126 | 127 | Help Options: 128 | -h, --help Show this help message 129 | 130 | [sort command options] 131 | -i, --input= the source to get json string from (mandatory) 132 | -o, --output= the output, default to stdout (default: -) 133 | ``` 134 | 135 | ### $ jsonfiddle j2s || true 136 | ```sh 137 | the required flag `-i, --input' was not specified 138 | 139 | Usage: 140 | jsonfiddle [OPTIONS] j2s [j2s-OPTIONS] 141 | 142 | JSON convert to Go struct 143 | 144 | Application Options: 145 | -c, --compact Compact JSON data, remove all whitespaces 146 | --prefix= prefix for json string output 147 | -d, --indent= indent for json string output (default: ) 148 | -p, --protect protect {{TEMPLATE}} in JSON data 149 | -v, --verbose Verbose mode (Multiple -v options increase the verbosity) 150 | -V, --version Show program version and exit 151 | 152 | Help Options: 153 | -h, --help Show this help message 154 | 155 | [j2s command options] 156 | -f, --fmt= the structural format of the input data (json/yaml) 157 | (default: json) 158 | -i, --input= the source of the input JSON (mandatory) 159 | -o, --output= the output, default to stdout (default: -) 160 | --name= the name of the root struct (default: as input file name) 161 | --pkg= the name of the package for the generated code (default: 162 | main) 163 | --subStruct create types for sub-structs 164 | ``` 165 | 166 | ### $ jsonfiddle x2j || true 167 | ```sh 168 | the required flag `-i, --input' was not specified 169 | 170 | Usage: 171 | jsonfiddle [OPTIONS] x2j [x2j-OPTIONS] 172 | 173 | Application Options: 174 | -c, --compact Compact JSON data, remove all whitespaces 175 | --prefix= prefix for json string output 176 | -d, --indent= indent for json string output (default: ) 177 | -p, --protect protect {{TEMPLATE}} in JSON data 178 | -v, --verbose Verbose mode (Multiple -v options increase the verbosity) 179 | -V, --version Show program version and exit 180 | 181 | Help Options: 182 | -h, --help Show this help message 183 | 184 | [x2j command options] 185 | -i, --input= the source of the input JSON (mandatory) 186 | -o, --output= the output, default to stdout (default: -) 187 | ``` 188 | 189 | # Examples 190 | 191 | ## Escape with `jsonfiddle esc` 192 | 193 | ### $ jsonfiddle esc -i test/Customer.ref 2>/dev/null 194 | ```json 195 | "{\n \"firstName\": \"John\",\n \"lastName\": \"Smith\",\n \"age\": 25,\n \"address\": {\n \"streetAddress\": \"21 2nd Street\",\n \"city\": \"New York\",\n \"state\": \"NY\",\n \"postalCode\": \"10021\"\n },\n \"phoneNumber\": [\n {\n \"type\": \"home\",\n \"number\": \"212 555-1234\"\n },\n {\n \"type\": \"fax\",\n \"number\": \"646 555-4567\"\n }\n ]\n}\n\n" 196 | ``` 197 | 198 | ### Usage 199 | 200 | `jsonfiddle esc` will escape any arbitrary string so as to embed it as content of json string. This seems useless at first, but it actually allows you to embed any arbitrary file into [GitHub Gists JSON API](https://developer.github.com/v3/gists/), so as to post any arbitrary file onto GitHub Gist: 201 | 202 | 203 | echo '{"description":"SmartyStreets API Demo","public":true,"files":{"SmartyStreets.json":{"content":'"`jsonfiddle fmt -i test/SmartyStreets.json | jsonfiddle esc -i`"'}}}' | curl --data @- https://api.github.com/gists 204 | 205 | This will give you 206 | https://gist.github.com/anonymous/1423d4768dd9b88262ca513626e68d8e 207 | 208 | 209 | By "_arbitrary file_" I do mean arbitrary file. Check this out: 210 | https://gist.github.com/anonymous/a51798ce99ff59d8d4ba536cbf4b6996 211 | 212 | This is why `jsonfiddle esc` is a command on its own, instead of being part of functionalities of `jsonfiddle fmt` or `jsonfiddle sort`. 213 | 214 | ## Format with `jsonfiddle fmt` 215 | 216 | ### Pretty print 217 | 218 | $ jsonfiddle fmt -i test/Customer.json 219 | 220 | #### > test/CustomerSI.ref 221 | ```json 222 | { 223 | "address": { 224 | "city": "New York", 225 | "postalCode": "10021", 226 | "state": "NY", 227 | "streetAddress": "21 2nd Street" 228 | }, 229 | "age": 25, 230 | "firstName": "John", 231 | "lastName": "Smith", 232 | "phoneNumber": [ 233 | { 234 | "number": "212 555-1234", 235 | "type": "home" 236 | }, 237 | { 238 | "number": "646 555-4567", 239 | "type": "fax" 240 | } 241 | ] 242 | } 243 | ``` 244 | 245 | ### Protect templates in json data 246 | 247 | There are times that json data may contain templates, i.e., strings like `{{VARIABLE}}`. Some of the pretty printing tools, like the json plugin in Notepad++, cannot handle such template forms well, and will turn `{{VARIABLE}}` into: 248 | 249 | ```json 250 | { 251 | { 252 | VARIABLE 253 | } 254 | } 255 | ``` 256 | 257 | What's worse is that when such template variables are for `int`, e.g.: `"age":{{Var_Age}}`, they then wouldn't be able to handle it, for inputs like 258 | test/CustomerP.json 259 | ```sh 260 | {"firstName":"{{C_firstName}}","lastName":"{{C_lastName}}","age":{{C_age}},"address":{"streetAddress":"{{C_address1}}","city":"{{C_city}}","state":"NY","postalCode":"10021"}} 261 | ``` 262 | 263 | To make such template variables work for those tools, the `-p,--protect` option is introduced: 264 | 265 | $ jsonfiddle fmt -p -i test/CustomerP.json 266 | 267 | #### > test/CustomerP.ref 268 | ```json 269 | { 270 | "firstName": "<>", 271 | "lastName": "<>", 272 | "age": "<>", 273 | "address": { 274 | "streetAddress": "<>", 275 | "city": "<>", 276 | "state": "NY", 277 | "postalCode": "10021" 278 | } 279 | } 280 | ``` 281 | 282 | ### Compact 283 | 284 | $ jsonfiddle fmt -c -i test/Customer.json 285 | 286 | #### > test/CustomerC.ref 287 | ```json 288 | {"firstName":"John","lastName":"Smith","age":25,"address":{"streetAddress":"21 2nd Street","city":"New York","state":"NY","postalCode":"10021"},"phoneNumber":[{"type":"home","number":"212 555-1234"},{"type":"fax","number":"646 555-4567"}]} 289 | ``` 290 | 291 | You can also do, 292 | 293 | $ cat Customer.json | jsonfiddle fmt -c -i - 294 | 295 | and the result is the same (and for all other examples using `-i` as well). 296 | 297 | ## Sort fields with `jsonfiddle sort` 298 | 299 | ### Sort in compact 300 | 301 | $ jsonfiddle sort -c -i test/Customer.json 302 | 303 | #### > test/CustomerSC.ref 304 | ```json 305 | {"address":{"city":"New York","postalCode":"10021","state":"NY","streetAddress":"21 2nd Street"},"age":25,"firstName":"John","lastName":"Smith","phoneNumber":[{"number":"212 555-1234","type":"home"},{"number":"646 555-4567","type":"fax"}]} 306 | ``` 307 | 308 | ### Sort with pretty print 309 | 310 | $ jsonfiddle sort -i test/Customer.json 311 | 312 | #### > test/CustomerSI.ref 313 | ```json 314 | { 315 | "address": { 316 | "city": "New York", 317 | "postalCode": "10021", 318 | "state": "NY", 319 | "streetAddress": "21 2nd Street" 320 | }, 321 | "age": 25, 322 | "firstName": "John", 323 | "lastName": "Smith", 324 | "phoneNumber": [ 325 | { 326 | "number": "212 555-1234", 327 | "type": "home" 328 | }, 329 | { 330 | "number": "646 555-4567", 331 | "type": "fax" 332 | } 333 | ] 334 | } 335 | ``` 336 | 337 | ### XML to JSON, sort then pretty print 338 | 339 | ``` 340 | $ jsonfiddle x2j -i test/Books.xml | jsonfiddle sort -i - | jsonfiddle fmt -i - 341 | XML to JSON 342 | jsonfiddle v0.5.0. x2j - XML to JSON 343 | Sort json fields recursively 344 | Format json string 345 | { 346 | "catalog": { 347 | "book": [ 348 | { 349 | "-id": "bk101", 350 | "author": "Gambardella, Matthew", 351 | "description": "An in-depth look at creating applications \n with XML.", 352 | "genre": "Computer", 353 | "price": "44.95", 354 | "publish_date": "2000-10-01", 355 | "title": "XML Developer's Guide" 356 | }, 357 | { 358 | "-id": "bk102", 359 | "author": "Ralls, Kim", 360 | "description": "A former architect battles corporate zombies, \n an evil sorceress, and her own childhood to become queen \n of the world.", 361 | "genre": "Fantasy", 362 | "price": "5.95", 363 | "publish_date": "2000-12-16", 364 | "title": "Midnight Rain" 365 | }, 366 | { 367 | "-id": "bk103", 368 | "author": "Corets, Eva", 369 | "description": "After the collapse of a nanotechnology \n society in England, the young survivors lay the \n foundation for a new society.", 370 | "genre": "Fantasy", 371 | "price": "5.95", 372 | "publish_date": "2000-11-17", 373 | "title": "Maeve Ascendant" 374 | } 375 | ] 376 | } 377 | } 378 | ``` 379 | 380 | ## JSON to struct via `jsonfiddle j2s` 381 | 382 | $ jsonfiddle j2s -i test/Customer.json 383 | 384 | #### > test/CustomerJ2S.ref 385 | ```go 386 | package main 387 | 388 | type Customer struct { 389 | Address struct { 390 | City string `json:"city"` 391 | PostalCode string `json:"postalCode"` 392 | State string `json:"state"` 393 | StreetAddress string `json:"streetAddress"` 394 | } `json:"address"` 395 | Age int64 `json:"age"` 396 | FirstName string `json:"firstName"` 397 | LastName string `json:"lastName"` 398 | PhoneNumber []struct { 399 | Number string `json:"number"` 400 | Type string `json:"type"` 401 | } `json:"phoneNumber"` 402 | } 403 | ``` 404 | 405 | 406 | # Purpose 407 | 408 | A few more words on why I'm writing the tool -- because I need to compare JSON string that are roughly close and very complicated in the mean time -- sometimes even less than 30% of fields are the same, of course, this is after their having been sorted, otherwise, it'd be 100% different. 409 | 410 | Thus all the JSON comparison tools I found are failing under such hash request. So far, I personally find that 411 | 412 | - Sorting the JSON data fields recursively and producing plain text file (via `jsonfiddle sort`), then use the state-of-the-art text comparison tools to compare them is the best approach, for my above scenario. 413 | - For extremely long and very complicated JSONs, converting json to abstract Go struct (via `jsonfiddle j2s`) is the quickest approach to compare them at higher level. 414 | 415 | # Download binaries 416 | 417 | - The latest binary executables are available under 418 | https://github.com/go-jsonfile/jsonfiddle/releases 419 | as the result of the Continuous-Integration process. 420 | - I.e., they are built right from the source code during every git tagging commit automatically. 421 | - Pick & choose the binary executable that suits your OS and its architecture. E.g., for Linux, it would most probably be the `jsonfiddle_linux_VER_amd64` file. If your OS and its architecture is not available in the download list, please let me know and I'll add it. 422 | - You may want to rename it to a shorter name instead, e.g., `jsonfiddle`, after downloading it. 423 | 424 | 425 | # Debian package 426 | 427 | Available at the above releases url as well. 428 | 429 | # Install Source 430 | 431 | To install the source code instead: 432 | 433 | ``` 434 | go get github.com/go-jsonfile/jsonfiddle 435 | ``` 436 | 437 | 438 | ## Credits 439 | 440 | - [Ladicle/gojson](https://github.com/Ladicle/gojson) forked source for JSON to struct 441 | - [ChimeraCoder/gojson](https://github.com/ChimeraCoder/gojson) the original source of [Ladicle/gojson](https://github.com/Ladicle/gojson). 442 | 443 | ## Similar Projects 444 | 445 | All the following similar projects have been considered before writing one on my own instead. 446 | 447 | . . . to be filled . . . 448 | 449 | ## Author(s) & Contributor(s) 450 | 451 | Tong SUN 452 | ![suntong from cpan.org](https://img.shields.io/badge/suntong-%40cpan.org-lightgrey.svg "suntong from cpan.org") 453 | 454 | _Powered by_ [**WireFrame**](https://github.com/go-easygen/wireframe), [![PoweredBy WireFrame](https://github.com/go-easygen/wireframe/blob/master/PoweredBy-WireFrame-Y.svg)](http://godoc.org/github.com/go-easygen/wireframe), the _one-stop wire-framing solution_ for Go cli based projects, from start to deploy. 455 | 456 | All patches welcome. 457 | -------------------------------------------------------------------------------- /cmd_esc.go: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // Program: jsonfiddle 3 | // Purpose: JSON Fiddling 4 | // Authors: Tong Sun (c) 2017-2023, All rights reserved 5 | //////////////////////////////////////////////////////////////////////////// 6 | 7 | package main 8 | 9 | import ( 10 | "fmt" 11 | "os" 12 | 13 | "github.com/go-easygen/go-flags/clis" 14 | ) 15 | 16 | // *** Sub-command: esc *** 17 | 18 | //////////////////////////////////////////////////////////////////////////// 19 | // Constant and data type/structure definitions 20 | 21 | // The EscCommand type defines all the configurable options from cli. 22 | type EscCommand struct { 23 | Filei string `short:"i" long:"input" description:"the source to get json string from (or \"-\" for stdin) (mandatory)" required:"true"` 24 | Fileo string `short:"o" long:"output" description:"the output, default to stdout" default:"-"` 25 | } 26 | 27 | var escCommand EscCommand 28 | 29 | //////////////////////////////////////////////////////////////////////////// 30 | // Function definitions 31 | 32 | func init() { 33 | gfParser.AddCommand("esc", 34 | "Escape json string", 35 | "", 36 | &escCommand) 37 | } 38 | 39 | func (x *EscCommand) Execute(args []string) error { 40 | fmt.Fprintf(os.Stderr, "Escape json string\n") 41 | // fmt.Fprintf(os.Stderr, "Copyright (C) 2017-2023, Tong Sun\n\n") 42 | clis.Setup("jsonfiddle::esc", opts.Verbose) 43 | clis.Verbose(1, "Doing Esc, with %+v, %+v", opts, args) 44 | // fmt.Println(x.Filei, x.Fileo) 45 | return x.Exec(args) 46 | } 47 | 48 | // // Exec implements the business logic of command `esc` 49 | // func (x *EscCommand) Exec(args []string) error { 50 | // // err := ... 51 | // // clis.WarnOn("esc::Exec", err) 52 | // // or, 53 | // // clis.AbortOn("esc::Exec", err) 54 | // return nil 55 | // } 56 | -------------------------------------------------------------------------------- /cmd_fmt.go: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // Program: jsonfiddle 3 | // Purpose: JSON Fiddling 4 | // Authors: Tong Sun (c) 2017-2023, All rights reserved 5 | //////////////////////////////////////////////////////////////////////////// 6 | 7 | package main 8 | 9 | import ( 10 | "fmt" 11 | "os" 12 | 13 | "github.com/go-easygen/go-flags/clis" 14 | ) 15 | 16 | // *** Sub-command: fmt *** 17 | 18 | //////////////////////////////////////////////////////////////////////////// 19 | // Constant and data type/structure definitions 20 | 21 | // The FmtCommand type defines all the configurable options from cli. 22 | type FmtCommand struct { 23 | Filei string `short:"i" long:"input" description:"the source to get json string from (mandatory)" required:"true"` 24 | Fileo string `short:"o" long:"output" description:"the output, default to stdout" default:"-"` 25 | } 26 | 27 | var fmtCommand FmtCommand 28 | 29 | //////////////////////////////////////////////////////////////////////////// 30 | // Function definitions 31 | 32 | func init() { 33 | gfParser.AddCommand("fmt", 34 | "Format json string", 35 | "", 36 | &fmtCommand) 37 | } 38 | 39 | func (x *FmtCommand) Execute(args []string) error { 40 | fmt.Fprintf(os.Stderr, "Format json string\n") 41 | // fmt.Fprintf(os.Stderr, "Copyright (C) 2017-2023, Tong Sun\n\n") 42 | clis.Setup("jsonfiddle::fmt", opts.Verbose) 43 | clis.Verbose(1, "Doing Fmt, with %+v, %+v", opts, args) 44 | // fmt.Println(x.Filei, x.Fileo) 45 | return x.Exec(args) 46 | } 47 | 48 | // // Exec implements the business logic of command `fmt` 49 | // func (x *FmtCommand) Exec(args []string) error { 50 | // // err := ... 51 | // // clis.WarnOn("fmt::Exec", err) 52 | // // or, 53 | // // clis.AbortOn("fmt::Exec", err) 54 | // return nil 55 | // } 56 | -------------------------------------------------------------------------------- /cmd_j2s.go: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // Program: jsonfiddle 3 | // Purpose: JSON Fiddling 4 | // Authors: Tong Sun (c) 2017-2023, All rights reserved 5 | //////////////////////////////////////////////////////////////////////////// 6 | 7 | package main 8 | 9 | import ( 10 | "fmt" 11 | "os" 12 | 13 | "github.com/go-easygen/go-flags/clis" 14 | ) 15 | 16 | // *** Sub-command: j2s *** 17 | 18 | //////////////////////////////////////////////////////////////////////////// 19 | // Constant and data type/structure definitions 20 | 21 | // The J2sCommand type defines all the configurable options from cli. 22 | type J2sCommand struct { 23 | FmtType string `short:"f" long:"fmt" description:"the structural format of the input data (json/yaml)" default:"json"` 24 | Filei string `short:"i" long:"input" description:"the source of the input JSON (mandatory)" required:"true"` 25 | Fileo string `short:"o" long:"output" description:"the output, default to stdout" default:"-"` 26 | Name string `long:"name" description:"the name of the root struct (default: as input file name)"` 27 | Pkg string `long:"pkg" description:"the name of the package for the generated code" default:"main"` 28 | SubStruct bool `long:"subStruct" description:"create types for sub-structs"` 29 | } 30 | 31 | var j2sCommand J2sCommand 32 | 33 | //////////////////////////////////////////////////////////////////////////// 34 | // Function definitions 35 | 36 | func init() { 37 | gfParser.AddCommand("j2s", 38 | "JSON to struct", 39 | "JSON convert to Go struct", 40 | &j2sCommand) 41 | } 42 | 43 | func (x *J2sCommand) Execute(args []string) error { 44 | fmt.Fprintf(os.Stderr, "JSON to struct\n") 45 | // fmt.Fprintf(os.Stderr, "Copyright (C) 2017-2023, Tong Sun\n\n") 46 | clis.Setup("jsonfiddle::j2s", opts.Verbose) 47 | clis.Verbose(1, "Doing J2s, with %+v, %+v", opts, args) 48 | // fmt.Println(x.FmtType, x.Filei, x.Fileo, x.Name, x.Pkg, x.SubStruct) 49 | return x.Exec(args) 50 | } 51 | 52 | // // Exec implements the business logic of command `j2s` 53 | // func (x *J2sCommand) Exec(args []string) error { 54 | // // err := ... 55 | // // clis.WarnOn("j2s::Exec", err) 56 | // // or, 57 | // // clis.AbortOn("j2s::Exec", err) 58 | // return nil 59 | // } 60 | -------------------------------------------------------------------------------- /cmd_sort.go: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // Program: jsonfiddle 3 | // Purpose: JSON Fiddling 4 | // Authors: Tong Sun (c) 2017-2023, All rights reserved 5 | //////////////////////////////////////////////////////////////////////////// 6 | 7 | package main 8 | 9 | import ( 10 | "fmt" 11 | "os" 12 | 13 | "github.com/go-easygen/go-flags/clis" 14 | ) 15 | 16 | // *** Sub-command: sort *** 17 | 18 | //////////////////////////////////////////////////////////////////////////// 19 | // Constant and data type/structure definitions 20 | 21 | // The SortCommand type defines all the configurable options from cli. 22 | type SortCommand struct { 23 | Filei string `short:"i" long:"input" description:"the source to get json string from (mandatory)" required:"true"` 24 | Fileo string `short:"o" long:"output" description:"the output, default to stdout" default:"-"` 25 | } 26 | 27 | var sortCommand SortCommand 28 | 29 | //////////////////////////////////////////////////////////////////////////// 30 | // Function definitions 31 | 32 | func init() { 33 | gfParser.AddCommand("sort", 34 | "Sort json fields recursively", 35 | "", 36 | &sortCommand) 37 | } 38 | 39 | func (x *SortCommand) Execute(args []string) error { 40 | fmt.Fprintf(os.Stderr, "Sort json fields recursively\n") 41 | // fmt.Fprintf(os.Stderr, "Copyright (C) 2017-2023, Tong Sun\n\n") 42 | clis.Setup("jsonfiddle::sort", opts.Verbose) 43 | clis.Verbose(1, "Doing Sort, with %+v, %+v", opts, args) 44 | // fmt.Println(x.Filei, x.Fileo) 45 | return x.Exec(args) 46 | } 47 | 48 | // // Exec implements the business logic of command `sort` 49 | // func (x *SortCommand) Exec(args []string) error { 50 | // // err := ... 51 | // // clis.WarnOn("sort::Exec", err) 52 | // // or, 53 | // // clis.AbortOn("sort::Exec", err) 54 | // return nil 55 | // } 56 | -------------------------------------------------------------------------------- /cmd_x2j.go: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // Program: jsonfiddle 3 | // Purpose: JSON Fiddling 4 | // Authors: Tong Sun (c) 2017-2023, All rights reserved 5 | //////////////////////////////////////////////////////////////////////////// 6 | 7 | package main 8 | 9 | import ( 10 | "fmt" 11 | "os" 12 | 13 | "github.com/go-easygen/go-flags/clis" 14 | ) 15 | 16 | // *** Sub-command: x2j *** 17 | 18 | //////////////////////////////////////////////////////////////////////////// 19 | // Constant and data type/structure definitions 20 | 21 | // The X2jCommand type defines all the configurable options from cli. 22 | type X2jCommand struct { 23 | Filei string `short:"i" long:"input" description:"the source of the input JSON (mandatory)" required:"true"` 24 | Fileo string `short:"o" long:"output" description:"the output, default to stdout" default:"-"` 25 | } 26 | 27 | var x2jCommand X2jCommand 28 | 29 | //////////////////////////////////////////////////////////////////////////// 30 | // Function definitions 31 | 32 | func init() { 33 | gfParser.AddCommand("x2j", 34 | "XML to JSON", 35 | "", 36 | &x2jCommand) 37 | } 38 | 39 | func (x *X2jCommand) Execute(args []string) error { 40 | fmt.Fprintf(os.Stderr, "XML to JSON\n") 41 | // fmt.Fprintf(os.Stderr, "Copyright (C) 2017-2023, Tong Sun\n\n") 42 | clis.Setup("jsonfiddle::x2j", opts.Verbose) 43 | clis.Verbose(1, "Doing X2j, with %+v, %+v", opts, args) 44 | // fmt.Println(x.Filei, x.Fileo) 45 | return x.Exec(args) 46 | } 47 | 48 | // // Exec implements the business logic of command `x2j` 49 | // func (x *X2jCommand) Exec(args []string) error { 50 | // // err := ... 51 | // // clis.WarnOn("x2j::Exec", err) 52 | // // or, 53 | // // clis.AbortOn("x2j::Exec", err) 54 | // return nil 55 | // } 56 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module jsonfiddle 2 | 3 | go 1.22.2 4 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go-jsonfile/jsonfiddle/0d86d0189bfd71466cb74f0209da81d96ce42b30/go.sum -------------------------------------------------------------------------------- /imp_esc.go: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // Program: jsonfiddle 3 | // Purpose: JSON Fiddling 4 | // Authors: Tong Sun (c) 2017-2023, All rights reserved 5 | //////////////////////////////////////////////////////////////////////////// 6 | 7 | package main 8 | 9 | import ( 10 | "encoding/json" 11 | "fmt" 12 | 13 | "github.com/go-easygen/go-flags/clis" 14 | ) 15 | 16 | // *** Sub-command: esc *** 17 | // Exec implements the business logic of command `esc` 18 | func (x *EscCommand) Exec(args []string) error { 19 | data := clis.ReadInput(x.Filei) 20 | 21 | out, err := json.Marshal(string(data)) 22 | clis.AbortOn("Formatting input", err) 23 | 24 | fileO := clis.GetOutputStream(x.Fileo) 25 | defer fileO.Close() 26 | 27 | fmt.Fprintf(fileO, "%s", out) 28 | return nil 29 | } 30 | -------------------------------------------------------------------------------- /imp_fmt.go: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // Program: jsonfiddle 3 | // Purpose: JSON Fiddling 4 | // Authors: Tong Sun (c) 2017-2023, All rights reserved 5 | //////////////////////////////////////////////////////////////////////////// 6 | 7 | package main 8 | 9 | import ( 10 | "bytes" 11 | "encoding/json" 12 | "fmt" 13 | 14 | "github.com/go-easygen/go-flags/clis" 15 | ) 16 | 17 | // *** Sub-command: fmt *** 18 | // Exec implements the business logic of command `fmt` 19 | func (x *FmtCommand) Exec(args []string) error { 20 | fileI := clis.GetInputStream(x.Filei) 21 | defer fileI.Close() 22 | data := readJson(fileI) 23 | 24 | var out bytes.Buffer 25 | var err error 26 | if opts.Compact { 27 | err = json.Compact(&out, data) 28 | } else { 29 | err = json.Indent(&out, data, opts.Prefix, opts.Indent) 30 | } 31 | clis.AbortOn("Formatting input", err) 32 | fileO := clis.GetOutputStream(x.Fileo) 33 | defer fileO.Close() 34 | out.WriteTo(fileO) 35 | fmt.Fprintln(fileO) 36 | return nil 37 | } 38 | -------------------------------------------------------------------------------- /imp_j2s.go: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // Program: jsonfiddle 3 | // Purpose: JSON Fiddling 4 | // Authors: Tong Sun (c) 2017-2023, All rights reserved 5 | //////////////////////////////////////////////////////////////////////////// 6 | 7 | package main 8 | 9 | import ( 10 | "fmt" 11 | "path/filepath" 12 | 13 | "github.com/go-easygen/go-flags/clis" 14 | "github.com/go-jsonfile/gojson" 15 | "github.com/suntong/enum" 16 | ) 17 | 18 | //////////////////////////////////////////////////////////////////////////// 19 | // Global variables definitions 20 | 21 | var ( 22 | fmtTypeEn = enum.NewEnum() 23 | fmtJson = fmtTypeEn.Iota("json") 24 | fmtYaml = fmtTypeEn.Iota("yaml") 25 | 26 | gjparser = []gojson.Parser{gojson.ParseJson, gojson.ParseYaml} 27 | ) 28 | 29 | //////////////////////////////////////////////////////////////////////////// 30 | // Function definitions 31 | 32 | // *** Sub-command: j2s *** 33 | // Exec implements the business logic of command `j2s` 34 | func (x *J2sCommand) Exec(args []string) error { 35 | fmtType, ok := fmtTypeEn.Get(x.FmtType) 36 | if !ok { 37 | clis.AbortOn("Get FmtType", fmt.Errorf("Invalid format string: '%s'\n", x.FmtType)) 38 | } 39 | nameRoot := clis.Basename(filepath.Base(x.Filei)) 40 | if len(x.Name) != 0 { 41 | nameRoot = x.Name 42 | } 43 | 44 | fileI := clis.GetInputStream(x.Filei) 45 | defer fileI.Close() 46 | output, err := gojson.Generate(fileI, gjparser[fmtType], 47 | nameRoot, x.Pkg, []string{x.FmtType}, x.SubStruct) 48 | clis.AbortOn("Gojson Parsing", err) 49 | 50 | fileO := clis.GetOutputStream(x.Fileo) 51 | defer fileO.Close() 52 | fmt.Fprint(fileO, string(output)) 53 | // clis.WarnOn("J2s, Exec", err) 54 | return nil 55 | } 56 | -------------------------------------------------------------------------------- /imp_sort.go: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // Program: jsonfiddle 3 | // Purpose: JSON Fiddling 4 | // Authors: Tong Sun (c) 2017-2023, All rights reserved 5 | //////////////////////////////////////////////////////////////////////////// 6 | 7 | package main 8 | 9 | import ( 10 | "encoding/json" 11 | "fmt" 12 | "io" 13 | 14 | "github.com/go-easygen/go-flags/clis" 15 | ) 16 | 17 | // *** Sub-command: sort *** 18 | // Exec implements the business logic of command `sort` 19 | func (x *SortCommand) Exec(args []string) error { 20 | fileI := clis.GetInputStream(x.Filei) 21 | defer fileI.Close() 22 | fileO := clis.GetOutputStream(x.Fileo) 23 | defer fileO.Close() 24 | 25 | return cmdSort(fileI, fileO) 26 | } 27 | 28 | //========================================================================== 29 | // support functions 30 | 31 | func cmdSort(r io.Reader, w io.Writer) error { 32 | var res interface{} 33 | content := readJson(r) 34 | json.Unmarshal(content, &res) 35 | var js []byte 36 | var err error 37 | if opts.Compact { 38 | js, err = json.Marshal(res) 39 | } else { 40 | js, err = json.MarshalIndent(res, opts.Prefix, opts.Indent) 41 | } 42 | clis.AbortOn("[::sort] Marshaling input", err) 43 | fmt.Fprintln(w, string(js)) 44 | return nil 45 | } 46 | -------------------------------------------------------------------------------- /imp_x2j.go: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // Program: jsonfiddle 3 | // Purpose: JSON Fiddling 4 | // Authors: Tong Sun (c) 2019-2023, All rights reserved 5 | //////////////////////////////////////////////////////////////////////////// 6 | 7 | package main 8 | 9 | import ( 10 | "fmt" 11 | "os" 12 | 13 | xj "github.com/basgys/goxml2json" 14 | 15 | "github.com/go-easygen/go-flags/clis" 16 | ) 17 | 18 | //////////////////////////////////////////////////////////////////////////// 19 | // x2j 20 | 21 | // *** Sub-command: x2j *** 22 | // Exec implements the business logic of command `x2j` 23 | func (x *X2jCommand) Exec(args []string) error { 24 | fmt.Fprintf(os.Stderr, "%s v%s. x2j - XML to JSON\n", progname, version) 25 | // err := ... 26 | // clis.WarnOn("X2j, Exec", err) 27 | fileI := clis.GetInputStream(x.Filei) 28 | defer fileI.Close() 29 | fileO := clis.GetOutputStream(x.Fileo) 30 | defer fileO.Close() 31 | 32 | json, err := xj.Convert(fileI) 33 | clis.AbortOn("Convert from xml to json", err) 34 | 35 | fmt.Fprintln(fileO, json.String()) 36 | return nil 37 | } 38 | -------------------------------------------------------------------------------- /jsonfiddle_cli.yaml: -------------------------------------------------------------------------------- 1 | # program name, name for the executable 2 | ProgramName: jsonfiddle 3 | Authors: Tong Sun 4 | Since: 2017 5 | 6 | PackageName: main 7 | 8 | Name: jsonfiddle 9 | Desc: "JSON Fiddling" 10 | Text: Tool to fiddle with json strings 11 | Verbose: true 12 | Version: true 13 | 14 | #UsageLead: "Usage:\\n jsonfiddle [Options] dir [dirs...]" 15 | 16 | Options: 17 | 18 | - Name: Compact 19 | Type: bool 20 | Flag: 'c,compact' 21 | Usage: Compact JSON data, remove all whitespaces 22 | 23 | - Name: Prefix 24 | Type: string 25 | Flag: 'prefix' 26 | Usage: prefix for json string output 27 | Value: '' 28 | 29 | - Name: Indent 30 | Type: string 31 | Flag: 'd,indent' 32 | Usage: indent for json string output 33 | Value: ' ' 34 | 35 | - Name: Protect 36 | Type: bool 37 | Flag: p,protect 38 | Usage: protect {{TEMPLATE}} in JSON data 39 | 40 | Command: 41 | 42 | - Name: esc 43 | Desc: "Escape json string" 44 | Text: '' 45 | #Text: 'Usage:\n jsonfiddle esc [Options]' 46 | 47 | Options: 48 | - Name: Filei 49 | Type: string 50 | Required: true 51 | Flag: 'i,input' 52 | Usage: 'the source to get json string from (or \"-\" for stdin) (mandatory)' 53 | 54 | - Name: Fileo 55 | Type: string 56 | Flag: o,output 57 | Value: "-" 58 | Usage: 'the output, default to stdout' 59 | 60 | - Name: fmt 61 | Desc: "Format json string" 62 | Text: '' 63 | #Text: 'Usage:\n jsonfiddle fmt [Options]' 64 | 65 | Options: 66 | - Name: Filei 67 | Type: string 68 | Required: true 69 | Flag: 'i,input' 70 | Usage: the source to get json string from (mandatory) 71 | 72 | - Name: Fileo 73 | Type: string 74 | Flag: o,output 75 | Value: "-" 76 | Usage: 'the output, default to stdout' 77 | 78 | - Name: sort 79 | Desc: "Sort json fields recursively" 80 | Text: '' 81 | #Text: 'Usage:\n jsonfiddle sort [Options]' 82 | 83 | Options: 84 | - Name: Filei 85 | Type: string 86 | Required: true 87 | Flag: 'i,input' 88 | Usage: the source to get json string from (mandatory) 89 | 90 | - Name: Fileo 91 | Type: string 92 | Flag: o,output 93 | Value: "-" 94 | Usage: 'the output, default to stdout' 95 | 96 | - Name: j2s 97 | Desc: "JSON to struct" 98 | Text: 'JSON convert to Go struct' 99 | #Text: 'Usage:\n jsonfiddle j2s [Options]' 100 | 101 | Options: 102 | 103 | - Name: FmtType 104 | Type: string 105 | Flag: f,fmt 106 | Usage: the structural format of the input data (json/yaml) 107 | Value: json 108 | 109 | - Name: Filei 110 | Type: string 111 | Required: true 112 | Flag: 'i,input' 113 | Usage: the source of the input JSON (mandatory) 114 | 115 | - Name: Fileo 116 | Type: string 117 | Flag: o,output 118 | Value: "-" 119 | Usage: 'the output, default to stdout' 120 | 121 | - Name: Name 122 | Type: string 123 | Flag: name 124 | Usage: 'the name of the root struct (default: as input file name)' 125 | 126 | - Name: Pkg 127 | Type: string 128 | Flag: pkg 129 | Usage: the name of the package for the generated code 130 | Value: main 131 | 132 | - Name: SubStruct 133 | Type: bool 134 | Flag: subStruct 135 | Usage: create types for sub-structs 136 | 137 | # - Name: tags 138 | # Type: string 139 | # Flag: tags 140 | # Usage: comma seperated list of the tags to put on the struct, default is the same as fmt 141 | # Value: fmt 142 | 143 | # - Name: ForceFloats 144 | # Type: bool 145 | # Flag: forcefloats 146 | # Usage: [experimental] force float64 type for integral values 147 | 148 | - Name: x2j 149 | Desc: "XML to JSON" 150 | Text: '' 151 | 152 | Options: 153 | 154 | - Name: Filei 155 | Type: string 156 | Required: true 157 | Flag: 'i,input' 158 | Usage: the source of the input JSON (mandatory) 159 | 160 | - Name: Fileo 161 | Type: string 162 | Flag: o,output 163 | Value: "-" 164 | Usage: 'the output, default to stdout' 165 | 166 | -------------------------------------------------------------------------------- /jsonfiddle_cliDef.go: -------------------------------------------------------------------------------- 1 | // jsonfiddle - JSON Fiddling 2 | // 3 | // Tool to fiddle with json strings 4 | 5 | package main 6 | 7 | //////////////////////////////////////////////////////////////////////////// 8 | // Program: jsonfiddle 9 | // Purpose: JSON Fiddling 10 | // Authors: Tong Sun (c) 2017-2023, All rights reserved 11 | //////////////////////////////////////////////////////////////////////////// 12 | 13 | import ( 14 | // "fmt" 15 | // "os" 16 | 17 | // "github.com/go-easygen/go-flags" 18 | ) 19 | 20 | // Template for main starts here 21 | 22 | ////////////////////////////////////////////////////////////////////////// 23 | // Constant and data type/structure definitions 24 | 25 | //////////////////////////////////////////////////////////////////////////// 26 | // Global variables definitions 27 | 28 | // var ( 29 | // progname = "jsonfiddle" 30 | // version = "0.1.0" 31 | // date = "2023-01-23" 32 | 33 | // // opts store all the configurable options 34 | // opts optsT 35 | // ) 36 | // 37 | // var gfParser = flags.NewParser(&opts, flags.Default) 38 | 39 | //////////////////////////////////////////////////////////////////////////// 40 | // Function definitions 41 | 42 | //========================================================================== 43 | // Function main 44 | // func main() { 45 | // opts.Version = showVersion 46 | // opts.Verbflg = func() { 47 | // opts.Verbose++ 48 | // } 49 | // 50 | // if _, err := gfParser.Parse(); err != nil { 51 | // fmt.Println() 52 | // gfParser.WriteHelp(os.Stdout) 53 | // os.Exit(1) 54 | // } 55 | // fmt.Println() 56 | // //DoJsonfiddle() 57 | // } 58 | // 59 | // //========================================================================== 60 | // // support functions 61 | // 62 | // func showVersion() { 63 | // fmt.Fprintf(os.Stderr, "jsonfiddle - JSON Fiddling, version %s\n", version) 64 | // fmt.Fprintf(os.Stderr, "Built on %s\n", date) 65 | // fmt.Fprintf(os.Stderr, "Copyright (C) 2017-2023, Tong Sun\n\n") 66 | // fmt.Fprintf(os.Stderr, "Tool to fiddle with json strings\n") 67 | // os.Exit(0) 68 | // } 69 | // Template for main ends here 70 | 71 | // DoJsonfiddle implements the business logic of command `jsonfiddle` 72 | // func DoJsonfiddle() error { 73 | // return nil 74 | // } 75 | 76 | // Template for type define starts here 77 | 78 | // The optsT type defines all the configurable options from cli. 79 | type optsT struct { 80 | Compact bool `short:"c" long:"compact" description:"Compact JSON data, remove all whitespaces"` 81 | Prefix string `long:"prefix" description:"prefix for json string output"` 82 | Indent string `short:"d" long:"indent" description:"indent for json string output" default:" "` 83 | Protect bool `short:"p" long:"protect" description:"protect {{TEMPLATE}} in JSON data"` 84 | Verbflg func() `short:"v" long:"verbose" description:"Verbose mode (Multiple -v options increase the verbosity)"` 85 | Verbose int 86 | Version func() `short:"V" long:"version" description:"Show program version and exit"` 87 | } 88 | 89 | // Template for type define ends here 90 | 91 | // Template for "esc" CLI handling starts here 92 | //////////////////////////////////////////////////////////////////////////// 93 | // Program: jsonfiddle 94 | // Purpose: JSON Fiddling 95 | // Authors: Tong Sun (c) 2017-2023, All rights reserved 96 | //////////////////////////////////////////////////////////////////////////// 97 | 98 | // package main 99 | 100 | // import ( 101 | // "fmt" 102 | // "os" 103 | // 104 | // "github.com/go-easygen/go-flags/clis" 105 | // ) 106 | 107 | // *** Sub-command: esc *** 108 | 109 | //////////////////////////////////////////////////////////////////////////// 110 | // Constant and data type/structure definitions 111 | 112 | // The EscCommand type defines all the configurable options from cli. 113 | // type EscCommand struct { 114 | // Filei string `short:"i" long:"input" description:"the source to get json string from (or \"-\" for stdin) (mandatory)" required:"true"` 115 | // Fileo string `short:"o" long:"output" description:"the output, default to stdout" default:"-"` 116 | // } 117 | 118 | // 119 | // var escCommand EscCommand 120 | // 121 | // //////////////////////////////////////////////////////////////////////////// 122 | // // Function definitions 123 | // 124 | // func init() { 125 | // gfParser.AddCommand("esc", 126 | // "Escape json string", 127 | // "", 128 | // &escCommand) 129 | // } 130 | // 131 | // func (x *EscCommand) Execute(args []string) error { 132 | // fmt.Fprintf(os.Stderr, "Escape json string\n") 133 | // // fmt.Fprintf(os.Stderr, "Copyright (C) 2017-2023, Tong Sun\n\n") 134 | // clis.Setup("jsonfiddle::esc", opts.Verbose) 135 | // clis.Verbose(1, "Doing Esc, with %+v, %+v", opts, args) 136 | // // fmt.Println(x.Filei, x.Fileo) 137 | // return x.Exec(args) 138 | // } 139 | // 140 | // // Exec implements the business logic of command `esc` 141 | // func (x *EscCommand) Exec(args []string) error { 142 | // // err := ... 143 | // // clis.WarnOn("esc::Exec", err) 144 | // // or, 145 | // // clis.AbortOn("esc::Exec", err) 146 | // return nil 147 | // } 148 | // Template for "esc" CLI handling ends here 149 | 150 | // Template for "fmt" CLI handling starts here 151 | //////////////////////////////////////////////////////////////////////////// 152 | // Program: jsonfiddle 153 | // Purpose: JSON Fiddling 154 | // Authors: Tong Sun (c) 2017-2023, All rights reserved 155 | //////////////////////////////////////////////////////////////////////////// 156 | 157 | // package main 158 | 159 | // import ( 160 | // "fmt" 161 | // "os" 162 | // 163 | // "github.com/go-easygen/go-flags/clis" 164 | // ) 165 | 166 | // *** Sub-command: fmt *** 167 | 168 | //////////////////////////////////////////////////////////////////////////// 169 | // Constant and data type/structure definitions 170 | 171 | // The FmtCommand type defines all the configurable options from cli. 172 | // type FmtCommand struct { 173 | // Filei string `short:"i" long:"input" description:"the source to get json string from (mandatory)" required:"true"` 174 | // Fileo string `short:"o" long:"output" description:"the output, default to stdout" default:"-"` 175 | // } 176 | 177 | // 178 | // var fmtCommand FmtCommand 179 | // 180 | // //////////////////////////////////////////////////////////////////////////// 181 | // // Function definitions 182 | // 183 | // func init() { 184 | // gfParser.AddCommand("fmt", 185 | // "Format json string", 186 | // "", 187 | // &fmtCommand) 188 | // } 189 | // 190 | // func (x *FmtCommand) Execute(args []string) error { 191 | // fmt.Fprintf(os.Stderr, "Format json string\n") 192 | // // fmt.Fprintf(os.Stderr, "Copyright (C) 2017-2023, Tong Sun\n\n") 193 | // clis.Setup("jsonfiddle::fmt", opts.Verbose) 194 | // clis.Verbose(1, "Doing Fmt, with %+v, %+v", opts, args) 195 | // // fmt.Println(x.Filei, x.Fileo) 196 | // return x.Exec(args) 197 | // } 198 | // 199 | // // Exec implements the business logic of command `fmt` 200 | // func (x *FmtCommand) Exec(args []string) error { 201 | // // err := ... 202 | // // clis.WarnOn("fmt::Exec", err) 203 | // // or, 204 | // // clis.AbortOn("fmt::Exec", err) 205 | // return nil 206 | // } 207 | // Template for "fmt" CLI handling ends here 208 | 209 | // Template for "sort" CLI handling starts here 210 | //////////////////////////////////////////////////////////////////////////// 211 | // Program: jsonfiddle 212 | // Purpose: JSON Fiddling 213 | // Authors: Tong Sun (c) 2017-2023, All rights reserved 214 | //////////////////////////////////////////////////////////////////////////// 215 | 216 | // package main 217 | 218 | // import ( 219 | // "fmt" 220 | // "os" 221 | // 222 | // "github.com/go-easygen/go-flags/clis" 223 | // ) 224 | 225 | // *** Sub-command: sort *** 226 | 227 | //////////////////////////////////////////////////////////////////////////// 228 | // Constant and data type/structure definitions 229 | 230 | // The SortCommand type defines all the configurable options from cli. 231 | // type SortCommand struct { 232 | // Filei string `short:"i" long:"input" description:"the source to get json string from (mandatory)" required:"true"` 233 | // Fileo string `short:"o" long:"output" description:"the output, default to stdout" default:"-"` 234 | // } 235 | 236 | // 237 | // var sortCommand SortCommand 238 | // 239 | // //////////////////////////////////////////////////////////////////////////// 240 | // // Function definitions 241 | // 242 | // func init() { 243 | // gfParser.AddCommand("sort", 244 | // "Sort json fields recursively", 245 | // "", 246 | // &sortCommand) 247 | // } 248 | // 249 | // func (x *SortCommand) Execute(args []string) error { 250 | // fmt.Fprintf(os.Stderr, "Sort json fields recursively\n") 251 | // // fmt.Fprintf(os.Stderr, "Copyright (C) 2017-2023, Tong Sun\n\n") 252 | // clis.Setup("jsonfiddle::sort", opts.Verbose) 253 | // clis.Verbose(1, "Doing Sort, with %+v, %+v", opts, args) 254 | // // fmt.Println(x.Filei, x.Fileo) 255 | // return x.Exec(args) 256 | // } 257 | // 258 | // // Exec implements the business logic of command `sort` 259 | // func (x *SortCommand) Exec(args []string) error { 260 | // // err := ... 261 | // // clis.WarnOn("sort::Exec", err) 262 | // // or, 263 | // // clis.AbortOn("sort::Exec", err) 264 | // return nil 265 | // } 266 | // Template for "sort" CLI handling ends here 267 | 268 | // Template for "j2s" CLI handling starts here 269 | //////////////////////////////////////////////////////////////////////////// 270 | // Program: jsonfiddle 271 | // Purpose: JSON Fiddling 272 | // Authors: Tong Sun (c) 2017-2023, All rights reserved 273 | //////////////////////////////////////////////////////////////////////////// 274 | 275 | // package main 276 | 277 | // import ( 278 | // "fmt" 279 | // "os" 280 | // 281 | // "github.com/go-easygen/go-flags/clis" 282 | // ) 283 | 284 | // *** Sub-command: j2s *** 285 | 286 | //////////////////////////////////////////////////////////////////////////// 287 | // Constant and data type/structure definitions 288 | 289 | // The J2sCommand type defines all the configurable options from cli. 290 | // type J2sCommand struct { 291 | // FmtType string `short:"f" long:"fmt" description:"the structural format of the input data (json/yaml)" default:"json"` 292 | // Filei string `short:"i" long:"input" description:"the source of the input JSON (mandatory)" required:"true"` 293 | // Fileo string `short:"o" long:"output" description:"the output, default to stdout" default:"-"` 294 | // Name string `long:"name" description:"the name of the root struct (default: as input file name)"` 295 | // Pkg string `long:"pkg" description:"the name of the package for the generated code" default:"main"` 296 | // SubStruct bool `long:"subStruct" description:"create types for sub-structs"` 297 | // } 298 | 299 | // 300 | // var j2sCommand J2sCommand 301 | // 302 | // //////////////////////////////////////////////////////////////////////////// 303 | // // Function definitions 304 | // 305 | // func init() { 306 | // gfParser.AddCommand("j2s", 307 | // "JSON to struct", 308 | // "JSON convert to Go struct", 309 | // &j2sCommand) 310 | // } 311 | // 312 | // func (x *J2sCommand) Execute(args []string) error { 313 | // fmt.Fprintf(os.Stderr, "JSON to struct\n") 314 | // // fmt.Fprintf(os.Stderr, "Copyright (C) 2017-2023, Tong Sun\n\n") 315 | // clis.Setup("jsonfiddle::j2s", opts.Verbose) 316 | // clis.Verbose(1, "Doing J2s, with %+v, %+v", opts, args) 317 | // // fmt.Println(x.FmtType, x.Filei, x.Fileo, x.Name, x.Pkg, x.SubStruct) 318 | // return x.Exec(args) 319 | // } 320 | // 321 | // // Exec implements the business logic of command `j2s` 322 | // func (x *J2sCommand) Exec(args []string) error { 323 | // // err := ... 324 | // // clis.WarnOn("j2s::Exec", err) 325 | // // or, 326 | // // clis.AbortOn("j2s::Exec", err) 327 | // return nil 328 | // } 329 | // Template for "j2s" CLI handling ends here 330 | 331 | // Template for "x2j" CLI handling starts here 332 | //////////////////////////////////////////////////////////////////////////// 333 | // Program: jsonfiddle 334 | // Purpose: JSON Fiddling 335 | // Authors: Tong Sun (c) 2017-2023, All rights reserved 336 | //////////////////////////////////////////////////////////////////////////// 337 | 338 | // package main 339 | 340 | // import ( 341 | // "fmt" 342 | // "os" 343 | // 344 | // "github.com/go-easygen/go-flags/clis" 345 | // ) 346 | 347 | // *** Sub-command: x2j *** 348 | 349 | //////////////////////////////////////////////////////////////////////////// 350 | // Constant and data type/structure definitions 351 | 352 | // The X2jCommand type defines all the configurable options from cli. 353 | // type X2jCommand struct { 354 | // Filei string `short:"i" long:"input" description:"the source of the input JSON (mandatory)" required:"true"` 355 | // Fileo string `short:"o" long:"output" description:"the output, default to stdout" default:"-"` 356 | // } 357 | 358 | // 359 | // var x2jCommand X2jCommand 360 | // 361 | // //////////////////////////////////////////////////////////////////////////// 362 | // // Function definitions 363 | // 364 | // func init() { 365 | // gfParser.AddCommand("x2j", 366 | // "XML to JSON", 367 | // "", 368 | // &x2jCommand) 369 | // } 370 | // 371 | // func (x *X2jCommand) Execute(args []string) error { 372 | // fmt.Fprintf(os.Stderr, "XML to JSON\n") 373 | // // fmt.Fprintf(os.Stderr, "Copyright (C) 2017-2023, Tong Sun\n\n") 374 | // clis.Setup("jsonfiddle::x2j", opts.Verbose) 375 | // clis.Verbose(1, "Doing X2j, with %+v, %+v", opts, args) 376 | // // fmt.Println(x.Filei, x.Fileo) 377 | // return x.Exec(args) 378 | // } 379 | // 380 | // // Exec implements the business logic of command `x2j` 381 | // func (x *X2jCommand) Exec(args []string) error { 382 | // // err := ... 383 | // // clis.WarnOn("x2j::Exec", err) 384 | // // or, 385 | // // clis.AbortOn("x2j::Exec", err) 386 | // return nil 387 | // } 388 | // Template for "x2j" CLI handling ends here 389 | -------------------------------------------------------------------------------- /jsonfiddle_cliGen.sh: -------------------------------------------------------------------------------- 1 | prj=jsonfiddle 2 | pwd=`pwd` 3 | srcDir=$GOPATH/src/github.com/go-easygen/easygen/test 4 | cd $srcDir || srcDir=/usr/share/gocode/src/github.com/go-easygen/easygen/test 5 | cd $srcDir || srcDir=/usr/share/doc/easygen/examples 6 | [ -d "$srcDir" ] || { 7 | echo No template file found 8 | exit 1 9 | } 10 | 11 | set -x 12 | 13 | cd $srcDir 14 | easygen commandlineGoFlags.header,commandlineGoFlags.ityped.tmpl,commandlineGoFlags "$pwd/$prj"_cli | gofmt > "$pwd/$prj"_cliDef.go 15 | 16 | cd $pwd 17 | go build -v 18 | echo ${prj}_cliDef.go generated successful 19 | -------------------------------------------------------------------------------- /jsonfiddle_main.go: -------------------------------------------------------------------------------- 1 | // jsonfiddle - JSON Fiddling 2 | 3 | // Tool to fiddle with json strings 4 | 5 | package main 6 | 7 | //////////////////////////////////////////////////////////////////////////// 8 | // Program: jsonfiddle 9 | // Purpose: JSON Fiddling 10 | // Authors: Tong Sun (c) 2017-2023, All rights reserved 11 | //////////////////////////////////////////////////////////////////////////// 12 | 13 | //go:generate sh jsonfiddle_cliGen.sh 14 | //go:generate emd gen -in README.e.md -out README.md 15 | 16 | import ( 17 | "fmt" 18 | "io" 19 | "io/ioutil" 20 | "os" 21 | "regexp" 22 | 23 | "github.com/go-easygen/go-flags" 24 | "github.com/go-easygen/go-flags/clis" 25 | ) 26 | 27 | ////////////////////////////////////////////////////////////////////////// 28 | // Constant and data type/structure definitions 29 | 30 | //////////////////////////////////////////////////////////////////////////// 31 | // Global variables definitions 32 | 33 | var ( 34 | progname = "jsonfiddle" 35 | version = "0.5.0" 36 | date = "2023-01-22" 37 | 38 | // opts store all the configurable options 39 | opts optsT 40 | ) 41 | 42 | var gfParser = flags.NewParser(&opts, flags.Default) 43 | 44 | //////////////////////////////////////////////////////////////////////////// 45 | // Function definitions 46 | 47 | //========================================================================== 48 | // Function main 49 | func main() { 50 | opts.Version = showVersion 51 | opts.Verbflg = func() { 52 | opts.Verbose++ 53 | } 54 | 55 | if _, err := gfParser.Parse(); err != nil { 56 | fmt.Println() 57 | gfParser.WriteHelp(os.Stdout) 58 | os.Exit(1) 59 | } 60 | fmt.Println() 61 | //DoJsonfiddle() 62 | } 63 | 64 | //========================================================================== 65 | // support functions 66 | 67 | func showVersion() { 68 | fmt.Fprintf(os.Stderr, "jsonfiddle - JSON Fiddling, version %s\n", version) 69 | fmt.Fprintf(os.Stderr, "Built on %s\n", date) 70 | fmt.Fprintf(os.Stderr, "Copyright (C) 2017-2023, Tong Sun\n\n") 71 | fmt.Fprintf(os.Stderr, "Tool to fiddle with json strings\n") 72 | os.Exit(0) 73 | } 74 | 75 | // readJson reads the given json file as []byte. 76 | func readJson(r io.Reader) []byte { 77 | data, err := ioutil.ReadAll(r) 78 | clis.AbortOn("Reading json input", err) 79 | 80 | if opts.Protect { 81 | data = regexp.MustCompile(`({{)([^ }]+)(}})`). 82 | ReplaceAll(data, []byte(`<<${2}>>`)) 83 | // "age":<> => "age":"<>" 84 | data = regexp.MustCompile(`(:)(<<[^>]+>>)([]},])`). 85 | ReplaceAll(data, []byte(`${1}"${2}"${3}`)) 86 | } 87 | clis.Verbose(2, "%s", string(data)) 88 | return data 89 | } 90 | -------------------------------------------------------------------------------- /jsonfiddle_test.go: -------------------------------------------------------------------------------- 1 | package main_test 2 | 3 | import ( 4 | "bytes" 5 | "os" 6 | "os/exec" 7 | "strings" 8 | "testing" 9 | ) 10 | 11 | const ( 12 | cmdTest = "jsonfiddle" 13 | dirTest = "test/" 14 | extRef = ".ref" // extension for reference file 15 | extGot = ".got" // extension for generated file 16 | ) 17 | 18 | // testIt runs @cmdEasyGen with @argv and compares the generated 19 | // output for @name with the corresponding @extRef 20 | func testIt(t *testing.T, name string, argv ...string) { 21 | var ( 22 | diffOut bytes.Buffer 23 | generatedOutput = name + extGot 24 | cmd = exec.Command(cmdTest, argv...) 25 | ) 26 | 27 | t.Logf("Testing %s:\n\t%s %s\n", name, cmdTest, strings.Join(argv, " ")) 28 | 29 | // open the out file for writing 30 | outfile, err := os.Create(generatedOutput) 31 | if err != nil { 32 | t.Errorf("write error [%s: %s] %s.", name, argv, err) 33 | } 34 | defer outfile.Close() 35 | cmd.Stdout = outfile 36 | 37 | err = cmd.Start() 38 | if err != nil { 39 | t.Errorf("start error [%s: %s] %s.", name, argv, err) 40 | } 41 | err = cmd.Wait() 42 | if err != nil { 43 | t.Errorf("exit error [%s: %s] %s.", name, argv, err) 44 | } 45 | 46 | cmd = exec.Command("diff", "-U1", name+extRef, generatedOutput) 47 | cmd.Stdout = &diffOut 48 | 49 | err = cmd.Start() 50 | if err != nil { 51 | t.Errorf("start error %s [%s: %s]", err, name, argv) 52 | } 53 | err = cmd.Wait() 54 | if err != nil { 55 | t.Errorf("cmp error %s [%s: %s]\n%s", err, name, argv, diffOut.String()) 56 | } 57 | //os.Remove(generatedOutput) 58 | } 59 | 60 | func TestExec(t *testing.T) { 61 | os.Chdir(dirTest) 62 | 63 | // == Test Basic Functions 64 | // -- fmt 65 | t.Logf("\n\n== Testing Basic fmt Functions\n\n") 66 | testIt(t, "CustomerC", "fmt", "-c", "-i", "Customer.json") 67 | testIt(t, "Customer", "fmt", "-i", "Customer.json") 68 | testIt(t, "Schedules", "fmt", "-i", "Schedules.json") 69 | testIt(t, "CustomerP", "fmt", "-p", "-i", "CustomerP.json") 70 | testIt(t, "CustomerPC", "fmt", "-c", "-p", "-i", "CustomerP.json") 71 | // -- sort 72 | t.Logf("\n\n== Testing Basic sort Functions\n\n") 73 | testIt(t, "CustomerSI", "sort", "-i", "Customer.json") 74 | testIt(t, "CustomerSC", "sort", "-c", "-i", "Customer.json") 75 | testIt(t, "CustomerPS", "sort", "-p", "-i", "CustomerP.json") 76 | testIt(t, "SchedulesSI", "sort", "-i", "Schedules.json") 77 | // -- j2s 78 | t.Logf("\n\n== Testing Basic j2s Functions\n\n") 79 | testIt(t, "CustomerJ2S", "j2s", "-i", "Customer.json") 80 | testIt(t, "GoodsJ2S", "j2s", "-i", "Goods.json") 81 | testIt(t, "MenuItemsJ2S", "j2s", "-i", "MenuItems.json") 82 | testIt(t, "SmartyStreetsJ2S", "j2s", "-i", "SmartyStreets.json") 83 | testIt(t, "SchedulesJ2S", "j2s", "-i", "Schedules.json") 84 | // -- x2j 85 | //t.Logf("\n\n== Testing Basic x2j Functions\n\n") 86 | //testIt(t, "Books", "x2j", "-i", "Books.xml") 87 | } 88 | -------------------------------------------------------------------------------- /test/Books.ref: -------------------------------------------------------------------------------- 1 | {"catalog": {"book": [{"-id": "bk101", "author": "Gambardella, Matthew", "title": "XML Developer's Guide", "genre": "Computer", "price": "44.95", "publish_date": "2000-10-01", "description": "An in-depth look at creating applications \n with XML."}, {"price": "5.95", "publish_date": "2000-12-16", "description": "A former architect battles corporate zombies, \n an evil sorceress, and her own childhood to become queen \n of the world.", "-id": "bk102", "author": "Ralls, Kim", "title": "Midnight Rain", "genre": "Fantasy"}, {"genre": "Fantasy", "price": "5.95", "publish_date": "2000-11-17", "description": "After the collapse of a nanotechnology \n society in England, the young survivors lay the \n foundation for a new society.", "-id": "bk103", "author": "Corets, Eva", "title": "Maeve Ascendant"}]}} 2 | 3 | -------------------------------------------------------------------------------- /test/Books.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Gambardella, Matthew 5 | XML Developer's Guide 6 | Computer 7 | 44.95 8 | 2000-10-01 9 | An in-depth look at creating applications 10 | with XML. 11 | 12 | 13 | Ralls, Kim 14 | Midnight Rain 15 | Fantasy 16 | 5.95 17 | 2000-12-16 18 | A former architect battles corporate zombies, 19 | an evil sorceress, and her own childhood to become queen 20 | of the world. 21 | 22 | 23 | Corets, Eva 24 | Maeve Ascendant 25 | Fantasy 26 | 5.95 27 | 2000-11-17 28 | After the collapse of a nanotechnology 29 | society in England, the young survivors lay the 30 | foundation for a new society. 31 | 32 | -------------------------------------------------------------------------------- /test/Customer.json: -------------------------------------------------------------------------------- 1 | {"firstName":"John","lastName":"Smith","age":25,"address":{"streetAddress":"21 2nd Street","city":"New York","state":"NY","postalCode":"10021"},"phoneNumber":[{"type":"home","number":"212 555-1234"},{"type":"fax","number":"646 555-4567"}]} 2 | -------------------------------------------------------------------------------- /test/Customer.ref: -------------------------------------------------------------------------------- 1 | { 2 | "firstName": "John", 3 | "lastName": "Smith", 4 | "age": 25, 5 | "address": { 6 | "streetAddress": "21 2nd Street", 7 | "city": "New York", 8 | "state": "NY", 9 | "postalCode": "10021" 10 | }, 11 | "phoneNumber": [ 12 | { 13 | "type": "home", 14 | "number": "212 555-1234" 15 | }, 16 | { 17 | "type": "fax", 18 | "number": "646 555-4567" 19 | } 20 | ] 21 | } 22 | 23 | -------------------------------------------------------------------------------- /test/CustomerC.ref: -------------------------------------------------------------------------------- 1 | Customer.json -------------------------------------------------------------------------------- /test/CustomerJ2S.ref: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | type Customer struct { 4 | Address struct { 5 | City string `json:"city"` 6 | PostalCode string `json:"postalCode"` 7 | State string `json:"state"` 8 | StreetAddress string `json:"streetAddress"` 9 | } `json:"address"` 10 | Age int64 `json:"age"` 11 | FirstName string `json:"firstName"` 12 | LastName string `json:"lastName"` 13 | PhoneNumber []struct { 14 | Number string `json:"number"` 15 | Type string `json:"type"` 16 | } `json:"phoneNumber"` 17 | } 18 | -------------------------------------------------------------------------------- /test/CustomerP.json: -------------------------------------------------------------------------------- 1 | {"firstName":"{{C_firstName}}","lastName":"{{C_lastName}}","age":{{C_age}},"address":{"streetAddress":"{{C_address1}}","city":"{{C_city}}","state":"NY","postalCode":"10021"}} 2 | -------------------------------------------------------------------------------- /test/CustomerP.ref: -------------------------------------------------------------------------------- 1 | { 2 | "firstName": "<>", 3 | "lastName": "<>", 4 | "age": "<>", 5 | "address": { 6 | "streetAddress": "<>", 7 | "city": "<>", 8 | "state": "NY", 9 | "postalCode": "10021" 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /test/CustomerPC.ref: -------------------------------------------------------------------------------- 1 | {"firstName":"<>","lastName":"<>","age":"<>","address":{"streetAddress":"<>","city":"<>","state":"NY","postalCode":"10021"}} 2 | -------------------------------------------------------------------------------- /test/CustomerPS.ref: -------------------------------------------------------------------------------- 1 | { 2 | "address": { 3 | "city": "\u003c\u003cC_city\u003e\u003e", 4 | "postalCode": "10021", 5 | "state": "NY", 6 | "streetAddress": "\u003c\u003cC_address1\u003e\u003e" 7 | }, 8 | "age": "\u003c\u003cC_age\u003e\u003e", 9 | "firstName": "\u003c\u003cC_firstName\u003e\u003e", 10 | "lastName": "\u003c\u003cC_lastName\u003e\u003e" 11 | } 12 | -------------------------------------------------------------------------------- /test/CustomerSC.ref: -------------------------------------------------------------------------------- 1 | {"address":{"city":"New York","postalCode":"10021","state":"NY","streetAddress":"21 2nd Street"},"age":25,"firstName":"John","lastName":"Smith","phoneNumber":[{"number":"212 555-1234","type":"home"},{"number":"646 555-4567","type":"fax"}]} 2 | -------------------------------------------------------------------------------- /test/CustomerSI.ref: -------------------------------------------------------------------------------- 1 | { 2 | "address": { 3 | "city": "New York", 4 | "postalCode": "10021", 5 | "state": "NY", 6 | "streetAddress": "21 2nd Street" 7 | }, 8 | "age": 25, 9 | "firstName": "John", 10 | "lastName": "Smith", 11 | "phoneNumber": [ 12 | { 13 | "number": "212 555-1234", 14 | "type": "home" 15 | }, 16 | { 17 | "number": "646 555-4567", 18 | "type": "fax" 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /test/Goods.json: -------------------------------------------------------------------------------- 1 | {"store":{"book":[{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"Evelyn Waugh","title":"Sword of Honour","price":12.99},{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99},{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the Rings","isbn":"0-395-19395-8","price":22.99}],"bicycle":{"color":"red","price":19.95}},"expensive":10} -------------------------------------------------------------------------------- /test/GoodsJ2S.ref: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | type Goods struct { 4 | Expensive int64 `json:"expensive"` 5 | Store struct { 6 | Bicycle struct { 7 | Color string `json:"color"` 8 | Price float64 `json:"price"` 9 | } `json:"bicycle"` 10 | Book []struct { 11 | Author string `json:"author"` 12 | Category string `json:"category"` 13 | Isbn string `json:"isbn"` 14 | Price float64 `json:"price"` 15 | Title string `json:"title"` 16 | } `json:"book"` 17 | } `json:"store"` 18 | } 19 | -------------------------------------------------------------------------------- /test/MenuItems.json: -------------------------------------------------------------------------------- 1 | {"menu":{"header":"xProgress SVG Viewer","items":[{"id":"Open"},{"id":"OpenNew","label":"Open New"},null,{"id":"ZoomIn","label":"Zoom In"},{"id":"ZoomOut","label":"Zoom Out"},{"id":"OriginalView","label":"Original View"},null,{"id":"Quality"},{"id":"Pause"},{"id":"Mute"},null,{"id":"Find","label":"Find..."},{"id":"FindAgain","label":"Find Again"},{"id":"Copy"},{"id":"CopyAgain","label":"Copy Again"},{"id":"CopySVG","label":"Copy SVG"},{"id":"ViewSVG","label":"View SVG"},{"id":"ViewSource","label":"View Source"},{"id":"SaveAs","label":"Save As"},null,{"id":"Help"},{"id":"About","label":"About xProgress CVG Viewer..."}]}} 2 | -------------------------------------------------------------------------------- /test/MenuItemsJ2S.ref: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | type MenuItems struct { 4 | Menu struct { 5 | Header string `json:"header"` 6 | Items []struct { 7 | ID string `json:"id"` 8 | } `json:"items"` 9 | } `json:"menu"` 10 | } 11 | -------------------------------------------------------------------------------- /test/Schedules.json: -------------------------------------------------------------------------------- 1 | {"DaysCfg":{"Range":{"lowerDate":"2017-07-28T00:00:00.000-04:00","upperDate":"2017-08-04T00:00:00.000-04:00"},"DaysInPeriod":8,"DaysToSchedule":[0,1,2,3,4,5,6]},"DepartmentsID":[138837,139734,141934,142436,149687,151049],"EmployeesID":[5039,5170,5889,6051,6236,7208,7281,8776,8781,8936,9261],"EndDate":"2017-08-03T23:59:00.000-04:00","IntervalSize":15,"IsActivitiesEnabled":true,"ModifyExisting":false,"OrignId":134721,"PrimaryOption":0,"SchoolDays":[],"ScheduleChanges":[],"StartDate":"2017-07-28T00:00:00.000-04:00","ZonesToSchedule":[5,4,6,3,3,3,2,14]} -------------------------------------------------------------------------------- /test/Schedules.ref: -------------------------------------------------------------------------------- 1 | { 2 | "DaysCfg": { 3 | "Range": { 4 | "lowerDate": "2017-07-28T00:00:00.000-04:00", 5 | "upperDate": "2017-08-04T00:00:00.000-04:00" 6 | }, 7 | "DaysInPeriod": 8, 8 | "DaysToSchedule": [ 9 | 0, 10 | 1, 11 | 2, 12 | 3, 13 | 4, 14 | 5, 15 | 6 16 | ] 17 | }, 18 | "DepartmentsID": [ 19 | 138837, 20 | 139734, 21 | 141934, 22 | 142436, 23 | 149687, 24 | 151049 25 | ], 26 | "EmployeesID": [ 27 | 5039, 28 | 5170, 29 | 5889, 30 | 6051, 31 | 6236, 32 | 7208, 33 | 7281, 34 | 8776, 35 | 8781, 36 | 8936, 37 | 9261 38 | ], 39 | "EndDate": "2017-08-03T23:59:00.000-04:00", 40 | "IntervalSize": 15, 41 | "IsActivitiesEnabled": true, 42 | "ModifyExisting": false, 43 | "OrignId": 134721, 44 | "PrimaryOption": 0, 45 | "SchoolDays": [], 46 | "ScheduleChanges": [], 47 | "StartDate": "2017-07-28T00:00:00.000-04:00", 48 | "ZonesToSchedule": [ 49 | 5, 50 | 4, 51 | 6, 52 | 3, 53 | 3, 54 | 3, 55 | 2, 56 | 14 57 | ] 58 | } 59 | -------------------------------------------------------------------------------- /test/SchedulesJ2S.ref: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | type Schedules struct { 4 | DaysCfg struct { 5 | DaysInPeriod int64 `json:"DaysInPeriod"` 6 | DaysToSchedule []int64 `json:"DaysToSchedule"` 7 | Range struct { 8 | LowerDate string `json:"lowerDate"` 9 | UpperDate string `json:"upperDate"` 10 | } `json:"Range"` 11 | } `json:"DaysCfg"` 12 | DepartmentsID []int64 `json:"DepartmentsID"` 13 | EmployeesID []int64 `json:"EmployeesID"` 14 | EndDate string `json:"EndDate"` 15 | IntervalSize int64 `json:"IntervalSize"` 16 | IsActivitiesEnabled bool `json:"IsActivitiesEnabled"` 17 | ModifyExisting bool `json:"ModifyExisting"` 18 | OrignID int64 `json:"OrignId"` 19 | PrimaryOption int64 `json:"PrimaryOption"` 20 | ScheduleChanges []interface{} `json:"ScheduleChanges"` 21 | SchoolDays []interface{} `json:"SchoolDays"` 22 | StartDate string `json:"StartDate"` 23 | ZonesToSchedule []int64 `json:"ZonesToSchedule"` 24 | } 25 | -------------------------------------------------------------------------------- /test/SchedulesSI.ref: -------------------------------------------------------------------------------- 1 | { 2 | "DaysCfg": { 3 | "DaysInPeriod": 8, 4 | "DaysToSchedule": [ 5 | 0, 6 | 1, 7 | 2, 8 | 3, 9 | 4, 10 | 5, 11 | 6 12 | ], 13 | "Range": { 14 | "lowerDate": "2017-07-28T00:00:00.000-04:00", 15 | "upperDate": "2017-08-04T00:00:00.000-04:00" 16 | } 17 | }, 18 | "DepartmentsID": [ 19 | 138837, 20 | 139734, 21 | 141934, 22 | 142436, 23 | 149687, 24 | 151049 25 | ], 26 | "EmployeesID": [ 27 | 5039, 28 | 5170, 29 | 5889, 30 | 6051, 31 | 6236, 32 | 7208, 33 | 7281, 34 | 8776, 35 | 8781, 36 | 8936, 37 | 9261 38 | ], 39 | "EndDate": "2017-08-03T23:59:00.000-04:00", 40 | "IntervalSize": 15, 41 | "IsActivitiesEnabled": true, 42 | "ModifyExisting": false, 43 | "OrignId": 134721, 44 | "PrimaryOption": 0, 45 | "ScheduleChanges": [], 46 | "SchoolDays": [], 47 | "StartDate": "2017-07-28T00:00:00.000-04:00", 48 | "ZonesToSchedule": [ 49 | 5, 50 | 4, 51 | 6, 52 | 3, 53 | 3, 54 | 3, 55 | 2, 56 | 14 57 | ] 58 | } 59 | -------------------------------------------------------------------------------- /test/SmartyStreets.json: -------------------------------------------------------------------------------- 1 | [{"input_index":0,"candidate_index":0,"delivery_line_1":"1 N Rosedale St","last_line":"Baltimore MD 21229-3737","delivery_point_barcode":"212293737013","components":{"primary_number":"1","street_predirection":"N","street_name":"Rosedale","street_suffix":"St","city_name":"Baltimore","state_abbreviation":"MD","zipcode":"21229","plus4_code":"3737","delivery_point":"01","delivery_point_check_digit":"3"},"metadata":{"record_type":"S","zip_type":"Standard","county_fips":"24510","county_name":"Baltimore City","carrier_route":"C047","congressional_district":"07","rdi":"Residential","elot_sequence":"0059","elot_sort":"A","latitude":39.28602,"longitude":-76.6689,"precision":"Zip9","time_zone":"Eastern","utc_offset":-5,"dst":true},"analysis":{"dpv_match_code":"Y","dpv_footnotes":"AABB","dpv_cmra":"N","dpv_vacant":"N","active":"Y"}},{"input_index":0,"candidate_index":1,"delivery_line_1":"1 S Rosedale St","last_line":"Baltimore MD 21229-3739","delivery_point_barcode":"212293739011","components":{"primary_number":"1","street_predirection":"S","street_name":"Rosedale","street_suffix":"St","city_name":"Baltimore","state_abbreviation":"MD","zipcode":"21229","plus4_code":"3739","delivery_point":"01","delivery_point_check_digit":"1"},"metadata":{"record_type":"S","zip_type":"Standard","county_fips":"24510","county_name":"Baltimore City","carrier_route":"C047","congressional_district":"07","rdi":"Residential","elot_sequence":"0064","elot_sort":"A","latitude":39.2858,"longitude":-76.66889,"precision":"Zip9","time_zone":"Eastern","utc_offset":-5,"dst":true},"analysis":{"dpv_match_code":"Y","dpv_footnotes":"AABB","dpv_cmra":"N","dpv_vacant":"N","active":"Y"}}] -------------------------------------------------------------------------------- /test/SmartyStreetsCLK.json: -------------------------------------------------------------------------------- 1 | [{"input-index":0,"candidate-index":0,"delivery-line-1":"1 n rosedale st","last-line":"baltimore md 21229-3737","delivery-point-barcode":"212293737013","components":{"primary-number":"1","street-predirection":"n","street-name":"rosedale","street-suffix":"st","city-name":"baltimore","state-abbreviation":"md","zipcode":"21229","plus4-code":"3737","delivery-point":"01","delivery-point-check-digit":"3"},"metadata":{"record-type":"s","zip-type":"standard","county-fips":"24510","county-name":"baltimore city","carrier-route":"c047","congressional-district":"07","rdi":"residential","elot-sequence":"0059","elot-sort":"a","latitude":39.28602,"longitude":-76.6689,"precision":"zip9","time-zone":"eastern","utc-offset":-5,"dst":true},"analysis":{"dpv-match-code":"y","dpv-footnotes":"aabb","dpv-cmra":"n","dpv-vacant":"n","active":"y"}},{"input-index":0,"candidate-index":1,"delivery-line-1":"1 s rosedale st","last-line":"baltimore md 21229-3739","delivery-point-barcode":"212293739011","components":{"primary-number":"1","street-predirection":"s","street-name":"rosedale","street-suffix":"st","city-name":"baltimore","state-abbreviation":"md","zipcode":"21229","plus4-code":"3739","delivery-point":"01","delivery-point-check-digit":"1"},"metadata":{"record-type":"s","zip-type":"standard","county-fips":"24510","county-name":"baltimore city","carrier-route":"c047","congressional-district":"07","rdi":"residential","elot-sequence":"0064","elot-sort":"a","latitude":39.2858,"longitude":-76.66889,"precision":"zip9","time-zone":"eastern","utc-offset":-5,"dst":true},"analysis":{"dpv-match-code":"y","dpv-footnotes":"aabb","dpv-cmra":"n","dpv-vacant":"n","active":"y"}}] -------------------------------------------------------------------------------- /test/SmartyStreetsCUC.json: -------------------------------------------------------------------------------- 1 | [{"InputIndex":0,"CandidateIndex":0,"DeliveryLine1":"1 N Rosedale St","LastLine":"Baltimore MD 21229-3737","DeliveryPointBarcode":"212293737013","Components":{"PrimaryNumber":"1","StreetPredirection":"N","StreetName":"Rosedale","StreetSuffix":"St","CityName":"Baltimore","StateAbbreviation":"MD","Zipcode":"21229","Plus4Code":"3737","DeliveryPoint":"01","DeliveryPointCheckDigit":"3"},"Metadata":{"RecordType":"S","ZipType":"Standard","CountyFips":"24510","CountyName":"Baltimore City","CarrierRoute":"C047","CongressionalDistrict":"07","Rdi":"Residential","ElotSequence":"0059","ElotSort":"A","Latitude":39.28602,"Longitude":-76.6689,"Precision":"Zip9","TimeZone":"Eastern","UtcOffset":-5,"Dst":true},"Analysis":{"DpvMatchCode":"Y","DpvFootnotes":"AABB","DpvCmra":"N","DpvVacant":"N","Active":"Y"}},{"InputIndex":0,"CandidateIndex":1,"DeliveryLine1":"1 S Rosedale St","LastLine":"Baltimore MD 21229-3739","DeliveryPointBarcode":"212293739011","Components":{"PrimaryNumber":"1","StreetPredirection":"S","StreetName":"Rosedale","StreetSuffix":"St","CityName":"Baltimore","StateAbbreviation":"MD","Zipcode":"21229","Plus4Code":"3739","DeliveryPoint":"01","DeliveryPointCheckDigit":"1"},"Metadata":{"RecordType":"S","ZipType":"Standard","CountyFips":"24510","CountyName":"Baltimore City","CarrierRoute":"C047","CongressionalDistrict":"07","Rdi":"Residential","ElotSequence":"0064","ElotSort":"A","Latitude":39.2858,"Longitude":-76.66889,"Precision":"Zip9","TimeZone":"Eastern","UtcOffset":-5,"Dst":true},"Analysis":{"DpvMatchCode":"Y","DpvFootnotes":"AABB","DpvCmra":"N","DpvVacant":"N","Active":"Y"}}] -------------------------------------------------------------------------------- /test/SmartyStreetsJ2S.ref: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | type SmartyStreets []struct { 4 | Analysis struct { 5 | Active string `json:"active"` 6 | DpvCmra string `json:"dpv_cmra"` 7 | DpvFootnotes string `json:"dpv_footnotes"` 8 | DpvMatchCode string `json:"dpv_match_code"` 9 | DpvVacant string `json:"dpv_vacant"` 10 | } `json:"analysis"` 11 | CandidateIndex int64 `json:"candidate_index"` 12 | Components struct { 13 | CityName string `json:"city_name"` 14 | DeliveryPoint string `json:"delivery_point"` 15 | DeliveryPointCheckDigit string `json:"delivery_point_check_digit"` 16 | Plus4Code string `json:"plus4_code"` 17 | PrimaryNumber string `json:"primary_number"` 18 | StateAbbreviation string `json:"state_abbreviation"` 19 | StreetName string `json:"street_name"` 20 | StreetPredirection string `json:"street_predirection"` 21 | StreetSuffix string `json:"street_suffix"` 22 | Zipcode string `json:"zipcode"` 23 | } `json:"components"` 24 | DeliveryLine1 string `json:"delivery_line_1"` 25 | DeliveryPointBarcode string `json:"delivery_point_barcode"` 26 | InputIndex int64 `json:"input_index"` 27 | LastLine string `json:"last_line"` 28 | Metadata struct { 29 | CarrierRoute string `json:"carrier_route"` 30 | CongressionalDistrict string `json:"congressional_district"` 31 | CountyFips string `json:"county_fips"` 32 | CountyName string `json:"county_name"` 33 | Dst bool `json:"dst"` 34 | ElotSequence string `json:"elot_sequence"` 35 | ElotSort string `json:"elot_sort"` 36 | Latitude float64 `json:"latitude"` 37 | Longitude float64 `json:"longitude"` 38 | Precision string `json:"precision"` 39 | Rdi string `json:"rdi"` 40 | RecordType string `json:"record_type"` 41 | TimeZone string `json:"time_zone"` 42 | UtcOffset int64 `json:"utc_offset"` 43 | ZipType string `json:"zip_type"` 44 | } `json:"metadata"` 45 | } 46 | -------------------------------------------------------------------------------- /test/friendfeed_oww.json: -------------------------------------------------------------------------------- 1 | [{ "_id" : "e/311a8abb31474a30a6e41e405ad163f7", "body" : "OWW Lab Notebook - http://openwetware.org/wiki...", "from" : { "type" : "user", "id" : "rvidal", "name" : "Ricardo Vidal" }, "url" : "http://friendfeed.com/oww/311a8abb/oww-lab-notebook", "to" : [ { "type" : "group", "name" : "OpenWetWare", "id" : "oww" } ], "date" : "2008-07-27T23:45:14Z", "feed_id" : "oww", "feed_name" : "OpenWetWare", "feed_description" : "Share your science", "feed_type" : "group" },{ "_id" : "e/5d2b5d3a8d3d425894e905206860f879", "body" : "Starting a page fro group edit on OWW. Are there any "how-to" pages for users that outline how to best use OWW for collaborative docs?", "from" : { "type" : "user", "id" : "ebola", "name" : "Maureen" }, "url" : "http://friendfeed.com/oww/5d2b5d3a/starting-page-fro-group-edit-on-oww-are-there-any", "comments" : [ { "date" : "2008-08-04T19:10:15Z", "body" : "Not that I know of - although such a thing would be useful. The key thing is to keep people engaged and contributing. Also to understand that different people have different comfort levels when it comes to editing other people's stuff.", "from" : { "type" : "user", "id" : "cameronneylon", "name" : "Cameron Neylon" }, "id" : "e/5d2b5d3a8d3d425894e905206860f879/c/79faf71b14314615bd845e81f488e7d8" }, { "date" : "2008-08-04T20:52:24Z", "body" : "Not quite sure we have a "How-to" for something like this. That's an interesting idea. Should we collaborate on a "how-to" collaborate page? :-)", "from" : { "type" : "user", "id" : "rvidal", "name" : "Ricardo Vidal" }, "id" : "e/5d2b5d3a8d3d425894e905206860f879/c/18e299578ec441168d14df88eb806819" }, { "date" : "2008-08-04T21:04:43Z", "body" : "Thanks Cameron and and Ricardo. I think a how-to page for document collaboration would be useful to organize work. For example, suggesting that edits go on the doc and comments or global changes go on the talk page. We could use the draft for the OWW NSF grant as an example perhaps. see talk page at http://openwetware.org/wiki...", "from" : { "type" : "user", "id" : "ebola", "name" : "Maureen" }, "id" : "e/5d2b5d3a8d3d425894e905206860f879/c/0cfe1eba4eed44aabca65b5eb9dc95aa" } ], "to" : [ { "type" : "group", "name" : "OpenWetWare", "id" : "oww" } ], "date" : "2008-08-04T18:21:03Z", "feed_id" : "oww", "feed_name" : "OpenWetWare", "feed_description" : "Share your science", "feed_type" : "group" },{ "_id" : "e/d2a16061f75b47d3a79b5d9c099397cb", "body" : "MyNetResearch | Online collaborative research community & tools - http://www.mynetresearch.com/Default...", "from" : { "type" : "user", "id" : "ebola", "name" : "Maureen" }, "url" : "http://friendfeed.com/oww/d2a16061/mynetresearch-online-collaborative-research", "to" : [ { "type" : "group", "name" : "OpenWetWare", "id" : "oww" } ], "likes" : [ { "date" : "2008-11-12T08:22:22Z", "from" : { "type" : "user", "id" : "shameer", "name" : "Khader Shameer" } } ], "date" : "2008-08-26T14:50:25Z", "feed_id" : "oww", "feed_name" : "OpenWetWare", "feed_description" : "Share your science", "feed_type" : "group" },{ "_id" : "e/d9b35157b7304b81a43e320922e19187", "body" : "Best Online Collaboration Tools 2008 - The Collaborative Map - http://www.masternewmedia.org/best-on...", "from" : { "type" : "user", "id" : "mikechelen", "name" : "Mike Chelen" }, "url" : "http://friendfeed.com/oww/d9b35157/best-online-collaboration-tools-2008", "to" : [ { "type" : "group", "name" : "OpenWetWare", "id" : "oww" } ], "likes" : [ { "date" : "2008-11-27T04:23:33Z", "from" : { "type" : "user", "id" : "nuin", "name" : "pn" } } ], "date" : "2008-11-27T04:17:13Z", "feed_id" : "oww", "feed_name" : "OpenWetWare", "feed_description" : "Share your science", "feed_type" : "group" },{ "_id" : "e/12b3340501ed4322802f2f79bd17dc5e", "body" : "Recent OWW site developments - http://groups.google.com/group...", "from" : { "type" : "user", "id" : "stevekoch", "name" : "Steve Koch" }, "url" : "http://friendfeed.com/oww/12b33405/recent-oww-site-developments", "comments" : [ { "date" : "2009-01-13T16:06:57Z", "body" : "Not sure if anyone uses this room, but thought I would share here.", "from" : { "type" : "user", "id" : "stevekoch", "name" : "Steve Koch" }, "id" : "e/12b3340501ed4322802f2f79bd17dc5e/c/2d1b461aa6ef4b878ded29ff3246f4de" }, { "date" : "2009-01-13T17:10:13Z", "body" : "I'm subscribed but there is not a lot of activity", "from" : { "type" : "user", "id" : "cameronneylon", "name" : "Cameron Neylon" }, "id" : "e/12b3340501ed4322802f2f79bd17dc5e/c/fedc882bd4d7444fa4e015ae49c23388" } ], "to" : [ { "type" : "group", "name" : "OpenWetWare", "id" : "oww" } ], "likes" : [ { "date" : "2009-01-13T17:22:09Z", "from" : { "type" : "user", "id" : "yokofakun", "name" : "Pierre Lindenbaum" } }, { "date" : "2009-01-13T17:09:55Z", "from" : { "type" : "user", "id" : "cameronneylon", "name" : "Cameron Neylon" } }, { "date" : "2009-01-13T16:25:08Z", "from" : { "type" : "user", "id" : "rvidal", "name" : "Ricardo Vidal" } } ], "date" : "2009-01-13T16:06:57Z", "feed_id" : "oww", "feed_name" : "OpenWetWare", "feed_description" : "Share your science", "feed_type" : "group" },{ "_id" : "e/313bfb22fdd6450ba0588f1cef82a29b", "body" : "Message from Bill about adding javascript gadgets to OWW. I don't understand it technically, but it sounds great to me. - http://groups.google.com/group...", "from" : { "type" : "user", "id" : "stevekoch", "name" : "Steve Koch" }, "url" : "http://friendfeed.com/oww/313bfb22/message-from-bill-about-adding-javascript", "to" : [ { "type" : "group", "name" : "OpenWetWare", "id" : "oww" } ], "date" : "2009-01-15T17:57:51Z", "feed_id" : "oww", "feed_name" : "OpenWetWare", "feed_description" : "Share your science", "feed_type" : "group" },{ "_id" : "e/1132852594744a2298d02958dda97051", "body" : "Javascript Gadgets Coming to OWW - http://blog.openwetware.org/communi...", "from" : { "type" : "user", "id" : "stevekoch", "name" : "Steve Koch" }, "url" : "http://friendfeed.com/oww/11328525/javascript-gadgets-coming-to-oww", "to" : [ { "type" : "group", "name" : "OpenWetWare", "id" : "oww" } ], "date" : "2009-01-18T14:20:03Z", "feed_id" : "oww", "feed_name" : "OpenWetWare", "feed_description" : "Share your science", "feed_type" : "group" },{ "_id" : "e/6a3c9db238184c2487693a51cc07f1b7", "body" : "Koch Lab Research blog about Andy's instructions for laser diode system. - http://kochlab.blogspot.com/2009...", "from" : { "type" : "user", "id" : "stevekoch", "name" : "Steve Koch" }, "url" : "http://friendfeed.com/oww/6a3c9db2/koch-lab-research-blog-about-andy-instructions", "comments" : [ { "date" : "2009-01-25T06:27:55Z", "body" : "I talk about a really cool page on how to assemble a laser diode system. Written by Andy Maloney, grad student in our lab, with help from other students.", "from" : { "type" : "user", "id" : "stevekoch", "name" : "Steve Koch" }, "id" : "e/6a3c9db238184c2487693a51cc07f1b7/c/6f2a9b1f8cf74e1db2b548cba5378679" }, { "date" : "2009-01-25T06:40:10Z", "body" : "Oh very cool. Brings back memories of my grad school days", "from" : { "type" : "user", "id" : "mndoci", "name" : "Deepak Singh" }, "id" : "e/6a3c9db238184c2487693a51cc07f1b7/c/4aae27f87cd64114b20536bb45646431" }, { "date" : "2009-01-25T06:51:28Z", "body" : "Thanks! And I hope it's bringing back the good memories :)", "from" : { "type" : "user", "id" : "stevekoch", "name" : "Steve Koch" }, "id" : "e/6a3c9db238184c2487693a51cc07f1b7/c/0eafefa517b44a72966d32bc1c8d6135" }, { "date" : "2009-01-25T06:57:32Z", "body" : "Most of them anyway :)", "from" : { "type" : "user", "id" : "mndoci", "name" : "Deepak Singh" }, "id" : "e/6a3c9db238184c2487693a51cc07f1b7/c/8b977295715c40f7b7af66add0481fe3" } ], "to" : [ { "type" : "group", "name" : "OpenWetWare", "id" : "oww" } ], "likes" : [ { "date" : "2009-01-25T13:26:22Z", "from" : { "type" : "user", "id" : "cameronneylon", "name" : "Cameron Neylon" } }, { "date" : "2009-01-25T06:40:03Z", "from" : { "type" : "user", "id" : "mndoci", "name" : "Deepak Singh" } } ], "date" : "2009-01-25T06:27:55Z", "feed_id" : "oww", "feed_name" : "OpenWetWare", "feed_description" : "Share your science", "feed_type" : "group" },{ "_id" : "e/51c8687c270f40a4bfd69da48d102b80", "body" : "Pipes: Filter OpenWetWare Feed - http://pipes.yahoo.com/skoch3...", "from" : { "type" : "user", "id" : "stevekoch", "name" : "Steve Koch" }, "url" : "http://friendfeed.com/oww/51c8687c/pipes-filter-openwetware-feed", "comments" : [ { "date" : "2009-02-05T09:55:13Z", "body" : "Steve, there is also a way of setting up a feed for a specific namespace at OWW. Have a look at the isisbio pages. Bill set this up a while back and we use it to pipe all of the changes on the wiki pages into the friendfeed room. That <startfeed/> creates a feed for all the subsidiary pages in the namespace ISISBio which you can see by pointing an RSS reader at http://openwetware.org/wiki...", "from" : { "type" : "user", "id" : "cameronneylon", "name" : "Cameron Neylon" }, "id" : "e/51c8687c270f40a4bfd69da48d102b80/c/204527598d4148448c2562ffc55a2c1b" }, { "date" : "2009-02-05T23:17:52Z", "body" : "Thanks, Cameron -- I didn't know about that. I think that looks good. The simple Pipe I created would be nice if you didn't want to add the <startfeed/> for whatever reason, or for other kinds of keyword feeding.", "from" : { "type" : "user", "id" : "stevekoch", "name" : "Steve Koch" }, "id" : "e/51c8687c270f40a4bfd69da48d102b80/c/eb209dbd67974503bc4beaccfb5e75df" } ], "to" : [ { "type" : "group", "name" : "OpenWetWare", "id" : "oww" } ], "likes" : [ { "date" : "2009-04-23T15:10:31Z", "from" : { "type" : "user", "id" : "danielmietchen", "name" : "Daniel Mietchen" } }, { "date" : "2009-02-05T10:35:17Z", "from" : { "type" : "user", "id" : "ebola", "name" : "Maureen" } }, { "date" : "2009-02-05T09:52:11Z", "from" : { "type" : "user", "id" : "cameronneylon", "name" : "Cameron Neylon" } } ], "date" : "2009-02-05T04:41:37Z", "feed_id" : "oww", "feed_name" : "OpenWetWare", "feed_description" : "Share your science", "feed_type" : "group" },{ "_id" : "e/a04ce3816fe34337b0a4b9cb31eefe28", "body" : "Can embed Google Docs spreadsheet in OWW pages now. - http://openwetware.org/wiki...", "from" : { "type" : "user", "id" : "stevekoch", "name" : "Steve Koch" }, "url" : "http://friendfeed.com/oww/a04ce381/can-embed-google-docs-spreadsheet-in-oww-pages", "comments" : [ { "date" : "2009-04-15T05:49:01Z", "body" : "Anthony inspired Bill Flanagan to roll out some spreadsheet (and other docs) stuff he's been working on recently. The link is to a page in Anthony's notebook using the embedded Google spreadsheet. I also think Bill either has or will enable similar features for embedding content from uploaded excel, word, and pdfs? Not really sure, but I think the ability to use spreadsheets is a huge bonus for OWW.", "from" : { "type" : "user", "id" : "stevekoch", "name" : "Steve Koch" }, "id" : "e/a04ce3816fe34337b0a4b9cb31eefe28/c/31fa5642c6f64617b98c8fba247d7044" }, { "date" : "2009-04-15T05:50:02Z", "body" : "There are some drawbacks still, I think -- for example, the data is at Google, not OWW, and I don't think Bill can access the data so it can be indexed and backed up at OWW. But maybe this problem can be solved in the future.", "from" : { "type" : "user", "id" : "stevekoch", "name" : "Steve Koch" }, "id" : "e/a04ce3816fe34337b0a4b9cb31eefe28/c/8ddbbf83eeb0468aa2d495ca7325734f" }, { "date" : "2009-04-15T05:50:39Z", "body" : "See related entry in Anthony's friendfeed: http://friendfeed.com/e...", "from" : { "type" : "user", "id" : "stevekoch", "name" : "Steve Koch" }, "id" : "e/a04ce3816fe34337b0a4b9cb31eefe28/c/23f5de611211411fbcd1fa4398182cd8" }, { "date" : "2009-04-15T06:02:37Z", "body" : "Also, Jean-Claude had a recent post related to automatic backup of Google spreadsheets and other things. I am lack too much understanding to comment, but it appears to me that all these things are related. See his post: http://friendfeed.com/e...", "from" : { "type" : "user", "id" : "stevekoch", "name" : "Steve Koch" }, "id" : "e/a04ce3816fe34337b0a4b9cb31eefe28/c/0e79d4f83d424ff0a485e8373fa8fd32" } ], "to" : [ { "type" : "group", "name" : "OpenWetWare", "id" : "oww" } ], "likes" : [ { "date" : "2010-02-08T23:45:50Z", "from" : { "type" : "user", "id" : "cboettig", "name" : "Carl Boettiger" } }, { "date" : "2009-04-16T05:36:33Z", "from" : { "type" : "user", "id" : "freesci", "name" : "Pawel Szczesny" } }, { "date" : "2009-04-15T07:55:41Z", "from" : { "type" : "user", "id" : "danielmietchen", "name" : "Daniel Mietchen" } }, { "date" : "2009-04-15T06:36:41Z", "from" : { "type" : "user", "id" : "benjamintseng", "name" : "Benjamin Tseng" } }, { "date" : "2009-04-15T05:59:39Z", "from" : { "type" : "user", "id" : "cameronneylon", "name" : "Cameron Neylon" } } ], "date" : "2009-04-15T05:45:02Z", "feed_id" : "oww", "feed_name" : "OpenWetWare", "feed_description" : "Share your science", "feed_type" : "group" },{ "_id" : "e/16d6c7a3aaa24d3984af823a310f194b", "body" : "Drew Endy's first blog post: State of the OWW | OpenWetWare Community - http://blog.openwetware.org/communi...", "via" : { "url" : "http://friendfeed.com/share/bookmarklet", "name" : "Bookmarklet" }, "from" : { "type" : "user", "id" : "stevekoch", "name" : "Steve Koch" }, "url" : "http://friendfeed.com/oww/16d6c7a3/drew-endy-first-blog-post-state-of-oww", "comments" : [ { "date" : "2009-06-12T16:27:26Z", "body" : "An excellent "state of the OWW" and call to action for all OWW users and potential users.", "via" : { "url" : "http://friendfeed.com/share/bookmarklet", "name" : "Bookmarklet" }, "from" : { "type" : "user", "id" : "stevekoch", "name" : "Steve Koch" }, "id" : "e/16d6c7a3aaa24d3984af823a310f194b/c/e0187c49d39044eead1d95f81b7d0352" }, { "date" : "2009-06-12T16:35:51Z", "body" : "An important discussion - where does it all go? And at the end of the day are we prepared to pay for it?", "from" : { "type" : "user", "id" : "cameronneylon", "name" : "Cameron Neylon" }, "id" : "e/16d6c7a3aaa24d3984af823a310f194b/c/269bd68986624af59ca34df73ce782c7" }, { "date" : "2009-06-13T02:05:50Z", "body" : "See also: http://friendfeed.com/openwet...", "from" : { "type" : "user", "id" : "stevekoch", "name" : "Steve Koch" }, "id" : "e/16d6c7a3aaa24d3984af823a310f194b/c/df0933b36027427496ac4b3a52c9021a" }, { "date" : "2009-06-15T07:53:22Z", "body" : "Thinking...", "from" : { "type" : "user", "id" : "alethea", "name" : "Heather" }, "id" : "e/16d6c7a3aaa24d3984af823a310f194b/c/121ce1631a544112930b239b51110a39" } ], "to" : [ { "type" : "user", "id" : "stevekoch", "name" : "Steve's feed" }, { "type" : "group", "name" : "OpenWetWare", "id" : "oww" }, { "type" : "group", "id" : "science-2-0", "name" : "Science 2.0" }, { "type" : "group", "id" : "the-life-scientists", "name" : "The Life Scientists" }, { "type" : "group", "id" : "kochlab", "name" : "Kochlab" } ], "likes" : [ { "date" : "2009-06-15T14:26:13Z", "from" : { "type" : "user", "id" : "aloisius", "name" : "Jordan M" } }, { "date" : "2009-06-15T07:53:12Z", "from" : { "type" : "user", "id" : "alethea", "name" : "Heather" } }, { "date" : "2009-06-13T09:59:28Z", "from" : { "type" : "user", "id" : "jcbradley", "name" : "Jean-Claude Bradley" } }, { "date" : "2009-06-13T06:15:46Z", "from" : { "type" : "user", "id" : "shwu", "name" : "Shirley Wu" } }, { "date" : "2009-06-12T18:50:40Z", "from" : { "type" : "user", "id" : "ruchira", "name" : "Ruchira S. Datta" } }, { "date" : "2009-06-12T16:51:07Z", "from" : { "type" : "user", "id" : "pedrobeltrao", "name" : "Pedro Beltrao" } }, { "date" : "2009-06-12T16:44:40Z", "from" : { "type" : "user", "id" : "sjcockell", "name" : "Simon Cockell" } }, { "date" : "2009-06-12T16:37:03Z", "from" : { "type" : "user", "id" : "michaelnielsen", "name" : "Michael Nielsen" } }, { "date" : "2009-06-12T16:35:27Z", "from" : { "type" : "user", "id" : "cameronneylon", "name" : "Cameron Neylon" } }, { "date" : "2009-06-12T16:28:56Z", "from" : { "type" : "user", "id" : "webmaven", "name" : "Michael R. Bernstein" } } ], "date" : "2009-06-12T16:27:26Z", "feed_id" : "oww", "feed_name" : "OpenWetWare", "feed_description" : "Share your science", "feed_type" : "group" },{ "_id" : "e/a67883bece6e4eb8b9879f6c31c927a8", "body" : "If you're interested in Biophysical Society Annual Meeting 2010 #BPS2010 in San Francisco, I created a FF room http://friendfeed.com/biophys...", "from" : { "type" : "user", "id" : "stevekoch", "name" : "Steve Koch" }, "url" : "http://friendfeed.com/kochlab/a67883be/if-you-re-interested-in-biophysical-society", "to" : [ { "type" : "user", "id" : "stevekoch", "name" : "Steve's feed" }, { "type" : "group", "id" : "kochlab", "name" : "Kochlab" }, { "type" : "group", "id" : "the-life-scientists", "name" : "The Life Scientists" }, { "type" : "group", "name" : "OpenWetWare", "id" : "oww" } ], "likes" : [ { "date" : "2010-02-06T19:32:41Z", "from" : { "type" : "user", "id" : "boudicca", "name" : "Lisa Green" } }, { "date" : "2009-08-20T14:05:12Z", "from" : { "type" : "user", "id" : "biehl", "name" : "Anders Norgaard" } } ], "date" : "2009-08-19T07:23:47Z", "feed_id" : "oww", "feed_name" : "OpenWetWare", "feed_description" : "Share your science", "feed_type" : "group" },{ "_id" : "e/6dec4105d99e4f7596e4dc7b5261604f", "body" : "Do you know of any examples of Open Notebook data being fetched automatically into a data repository on a regular basis?", "from" : { "type" : "user", "id" : "danielmietchen", "name" : "Daniel Mietchen" }, "url" : "http://friendfeed.com/oww/6dec4105/do-you-know-of-any-examples-open-notebook-data", "comments" : [ { "date" : "2009-09-10T14:01:17Z", "body" : "I think Egon is working on something along those lines for the Solubility data. None of our data is structured enough to make this easy at the moment.", "from" : { "type" : "user", "id" : "cameronneylon", "name" : "Cameron Neylon" }, "id" : "e/6dec4105d99e4f7596e4dc7b5261604f/c/e576d021b6244c70b3e650c42b5d1780" }, { "date" : "2009-09-10T18:33:34Z", "body" : "Thanks, Cameron. I am currently back to the "What would science look like if it were invented today" draft ( http://en.wikiversity.org/wiki... ) and would like to mention such examples there, along with the exciting prospect of harvesting data repositories to put the data in context, as http://en.wikipedia.org/wiki... does it for Genes.", "from" : { "type" : "user", "id" : "danielmietchen", "name" : "Daniel Mietchen" }, "id" : "e/6dec4105d99e4f7596e4dc7b5261604f/c/9089425152f94a779eb975d1a8c4e78f" } ], "to" : [ { "type" : "user", "id" : "danielmietchen", "name" : "Daniel's feed" }, { "type" : "group", "name" : "OpenWetWare", "id" : "oww" } ], "likes" : [ { "date" : "2009-09-10T16:57:35Z", "from" : { "type" : "user", "id" : "paulsb", "private" : true, "name" : "Paul Bacchus" } }, { "date" : "2009-09-10T15:01:07Z", "from" : { "type" : "user", "id" : "claudiakoltzenburg", "name" : "Claudia Koltzenburg" } }, { "date" : "2009-09-10T14:01:23Z", "from" : { "type" : "user", "id" : "cameronneylon", "name" : "Cameron Neylon" } } ], "date" : "2009-09-10T13:57:00Z", "feed_id" : "oww", "feed_name" : "OpenWetWare", "feed_description" : "Share your science", "feed_type" : "group" },{ "_id" : "e/9421ccf89100483998d229eb50856d85", "body" : "Model notebook, combo FriendFeed with MediaWiki (OpenWetWare) - http://openwetware.org/wiki...", "via" : { "url" : "http://friendfeed.com/share/bookmarklet", "name" : "Bookmarklet" }, "from" : { "type" : "user", "id" : "stevekoch", "name" : "Steve Koch" }, "url" : "http://friendfeed.com/science-2-0/9421ccf8/model-notebook-combo-friendfeed-with", "comments" : [ { "date" : "2010-01-30T03:48:26Z", "body" : "I have been thinking for several months that FriendFeed is very close to what I need for a lab notebook. This page is to help me think about that. The main thing missing at the moment (it seems) is just a way to filter FriendFeed stuff by date. There's also the issue that the wiki doesn't "know" the FriendFeed content, and so versioning stuff is lost. But seems to me many of the pieces are there.", "via" : { "url" : "http://friendfeed.com/share/bookmarklet", "name" : "Bookmarklet" }, "from" : { "type" : "user", "id" : "stevekoch", "name" : "Steve Koch" }, "id" : "e/9421ccf89100483998d229eb50856d85/c/1db3f737ce3041cfa894b0490fb849b0" }, { "date" : "2010-01-30T04:05:19Z", "body" : "One valid question would be: "is there a point to the wiki?" I'm thinking not a whole lot, right now I'm just using it as an easy way to place in a few iframes of the friend feed threads. A really advanced mindmap that I could drag and drop FriendFeed threads around, and then describe relationships between feeds would be very cool. Of course, I'm biased that way because I learned how mindmaps work last night and looked into them today.", "from" : { "type" : "user", "id" : "stevekoch", "name" : "Steve Koch" }, "id" : "e/9421ccf89100483998d229eb50856d85/c/d93b0617269a4ad882ddfc58282186d9" }, { "date" : "2010-01-30T05:36:56Z", "body" : "Breakin' the law! I'm so cool. Here's some non-science for you: http://friendfeed.com/steveko...", "from" : { "type" : "user", "id" : "stevekoch", "name" : "Steve Koch" }, "id" : "e/9421ccf89100483998d229eb50856d85/c/9461822a35f746098d43a876d4c82768" }, { "date" : "2010-01-30T06:40:00Z", "body" : "I would say that there is a point to the wiki. Mainly because you can embed video, use LaTeX, Google spreadsheets, etc. Plus the wiki markup allows for greater structure in a post (headings, links...). Now if we use the power of the wiki with the flexibility for posting things via Friendfeed, that's spectacular. The ability to post relevent conversations on Friendfeed to a notebook entry is pretty awesome. I actually can't wait to try this.", "via" : { "url" : "http://friendfeed.com/about/tools", "name" : "iPhone" }, "from" : { "type" : "user", "id" : "andymaloney", "name" : "Andy Maloney" }, "id" : "e/9421ccf89100483998d229eb50856d85/c/1adee48f7ce54257b0553208ff40a0e6" }, { "date" : "2010-01-30T09:07:11Z", "body" : "I also like the wiki because I am more of a wet lab person, and it more resembles a lab notebook to me - way to paste in various pieces of information as Andy wrote. Will follow this with much interest.", "from" : { "type" : "user", "id" : "alethea", "name" : "Heather" }, "id" : "e/9421ccf89100483998d229eb50856d85/c/563e1558bedf45d781a51db819456fd4" }, { "date" : "2010-01-30T10:54:54Z", "body" : "I've been using the wiki within our institutional VLE for over a year (giving up the paper notebooks was v. difficult!;) The flexibility is key: got to be able to post / upload anything. Am working on a "parts list" for diagrams that are used frequently (sequence maps, pcr primers etc) mostly generated spontaneously by students. Anybody know of an online source of such things?", "via" : { "url" : "http://www.nambu.com/", "name" : "Nambu" }, "from" : { "type" : "user", "id" : "richardbadge", "name" : "Richard Badge" }, "id" : "e/9421ccf89100483998d229eb50856d85/c/9c329b5ca7e449059ea5c1939c98dad0" }, { "date" : "2010-02-11T15:31:28Z", "body" : "Ant also asked this question, "do you need OWW?" I think if OWW can transform to make this work, then it'd be a "yes," since it could be very flexible. I had to create this example page manually. The next version of OWW (or other VLE or whatever) needs to be able to create pages automatically. So, when I create a new gel photo it automatically goes in my "gels" section of that day's page. It's OK if I need to do some setup work, but I shouldn't have to manually do stuff every day.", "from" : { "type" : "user", "id" : "stevekoch", "name" : "Steve Koch" }, "id" : "e/9421ccf89100483998d229eb50856d85/c/546f7f772f414014af4546115c2d6241" }, { "date" : "2010-02-11T17:49:16Z", "body" : "I do not think imagining a FF widget is too far off: http://openwetware.org/wiki... .", "from" : { "type" : "user", "id" : "danielmietchen", "name" : "Daniel Mietchen" }, "id" : "e/9421ccf89100483998d229eb50856d85/c/34d1d26fddc94f00a66703f0b09b3bd0" }, { "date" : "2010-02-11T21:19:31Z", "body" : "It's times like this I feel the lack of a DropBox API - but we do have a grant in to develop a really lightweight, "drop it in the appropriate folder and have it go to the right place" system. That could work with the MediaWiki API (or anything else) to enable a bit of this kind of thing. But agree with Richard, its nice if a system knows what to do with a particular file type, but the important thing is that you can upload anything at all.", "from" : { "type" : "user", "id" : "cameronneylon", "name" : "Cameron Neylon" }, "id" : "e/9421ccf89100483998d229eb50856d85/c/7d12481b0f964eb3851af2c5653908ec" }, { "date" : "2010-02-12T01:43:19Z", "body" : "I think that it has all been mentioned already, but I just want to emphasize what Andy pointed out. The the wiki gives your information some structure, mostly in regards to non-notebook information. As great as the lab notebook format that the wiki provides is, as I've had less and less time during the past few months, it has become more annoying to manually upload files/enter entries for my notebook using the wiki, especially once I fall behind updating things. I've been using google docs instead and just keeping the files that I would've normally uploaded on my computer for now. In an ideal world, I'd like to work on a "cloud" that would keep all of my work stuff available to me at home without the use of VPN or a server (actually something in between using a lab network and a wiki). Sorry for the rant, this new FF capability is cool though :)", "from" : { "type" : "user", "id" : "ramalldf", "name" : "Diego" }, "id" : "e/9421ccf89100483998d229eb50856d85/c/7c5b1434479942faa02220d464e82f73" } ], "to" : [ { "type" : "user", "id" : "stevekoch", "name" : "Steve's feed" }, { "type" : "group", "id" : "science-2-0", "name" : "Science 2.0" }, { "type" : "group", "id" : "the-life-scientists", "name" : "The Life Scientists" }, { "type" : "group", "name" : "OpenWetWare", "id" : "oww" }, { "type" : "group", "id" : "eresearch", "name" : "eResearch & ScholComm" } ], "likes" : [ { "date" : "2010-02-11T18:53:27Z", "from" : { "type" : "user", "id" : "bersenev", "name" : "Alexey" } }, { "date" : "2010-02-11T15:56:13Z", "from" : { "type" : "user", "id" : "tomtullius", "name" : "Tom Tullius" } }, { "date" : "2010-02-01T12:29:53Z", "from" : { "type" : "user", "id" : "graymills", "name" : "Peter Miller" } }, { "date" : "2010-02-01T11:55:35Z", "from" : { "type" : "user", "id" : "danielmietchen", "name" : "Daniel Mietchen" } }, { "date" : "2010-01-30T21:32:14Z", "from" : { "type" : "user", "id" : "freesci", "name" : "Pawel Szczesny" } }, { "date" : "2010-01-30T20:25:27Z", "from" : { "type" : "user", "id" : "billhooker", "name" : "Bill Hooker" } }, { "date" : "2010-01-30T18:00:09Z", "from" : { "type" : "user", "id" : "msscha", "name" : "Mickey Schafer" } }, { "date" : "2010-01-30T10:49:27Z", "from" : { "type" : "user", "id" : "richardbadge", "name" : "Richard Badge" } }, { "date" : "2010-01-30T09:59:43Z", "from" : { "type" : "user", "id" : "scilib", "name" : "Richard Akerman" } }, { "date" : "2010-01-30T08:34:57Z", "from" : { "type" : "user", "id" : "alethea", "name" : "Heather" } }, { "date" : "2010-01-30T04:18:38Z", "from" : { "type" : "user", "id" : "imabonehead", "private" : true, "name" : "imabonehead" } }, { "date" : "2010-01-30T04:10:55Z", "from" : { "type" : "user", "id" : "ruchira", "name" : "Ruchira S. Datta" } } ], "date" : "2010-01-30T03:48:26Z", "feed_id" : "oww", "feed_name" : "OpenWetWare", "feed_description" : "Share your science", "feed_type" : "group" },{ "_id" : "e/494128a2893e4bd2acac425b4e00518b", "body" : "More Open Notebook Science! Carl Boettiger, grad at UC-Davis. - http://openwetware.org/wiki...", "via" : { "url" : "http://friendfeed.com/share/bookmarklet", "name" : "Bookmarklet" }, "from" : { "type" : "user", "id" : "stevekoch", "name" : "Steve Koch" }, "url" : "http://friendfeed.com/science-2-0/494128a2/more-open-notebook-science-carl-boettiger-grad", "comments" : [ { "date" : "2010-02-05T19:20:24Z", "body" : "Has two notebooks so far, this one and also another, both using the wiki on OpenWetWare: http://openwetware.org/wiki...", "via" : { "url" : "http://friendfeed.com/share/bookmarklet", "name" : "Bookmarklet" }, "from" : { "type" : "user", "id" : "stevekoch", "name" : "Steve Koch" }, "id" : "e/494128a2893e4bd2acac425b4e00518b/c/fbb944e7f38441b98902dfb574bb4530" }, { "date" : "2010-02-05T19:21:24Z", "body" : "Here's Carl's friendfeed: http://friendfeed.com/cboettig", "from" : { "type" : "user", "id" : "stevekoch", "name" : "Steve Koch" }, "id" : "e/494128a2893e4bd2acac425b4e00518b/c/649fd6c8ab3f4c6d9d6984d2d3228e6b" }, { "date" : "2010-02-05T19:22:44Z", "body" : "Carl says that KochLab students' ONS on OWW partly inspired him to start his own open notebooks. That makes me happy! Props to Carl & Anthony, Larry, Andy, Brian, ...", "from" : { "type" : "user", "id" : "stevekoch", "name" : "Steve Koch" }, "id" : "e/494128a2893e4bd2acac425b4e00518b/c/647d287ce8b543d797ac534612fc1ad8" }, { "date" : "2010-02-05T21:01:52Z", "body" : "One of us! One of us! :-) :-) This makes me very happy.", "from" : { "type" : "user", "id" : "billhooker", "name" : "Bill Hooker" }, "id" : "e/494128a2893e4bd2acac425b4e00518b/c/1ca67ea797494d93978c5d71cbfd1a4a" }, { "date" : "2010-02-05T21:59:23Z", "body" : ""I'm an Open Scientist and this is what I do!" I agree with Bill. This makes me very happy!", "from" : { "type" : "user", "id" : "anthonysalvagno", "name" : "Anthony Salvagno" }, "id" : "e/494128a2893e4bd2acac425b4e00518b/c/00ad6ca5bb2f46f6b0463bc408e4308d" }, { "date" : "2010-02-06T14:21:57Z", "body" : "nice! Are these examples of theoretical notebooks? http://en.wikipedia.org/wiki...", "from" : { "type" : "user", "id" : "jcbradley", "name" : "Jean-Claude Bradley" }, "id" : "e/494128a2893e4bd2acac425b4e00518b/c/afe0bd084358440e9f4e2ed542aee570" }, { "date" : "2010-02-06T15:53:16Z", "body" : "I added his two notebooks under the theory section. As I understand it, it's theory + computational modeling. Computational modeling can be in either in my opinion--the kind of results generated are probably more like lab experiments than theory. So, probably there's need for far more than two categories. Plus, that section of notebooks examples is getting too big! That's a good thing, but I think a couple "examples" should be put in that section, and then the rest should be put in a new page, "Examples of ONS practitioners." Or at least, that section should be moved to the end of the article?", "from" : { "type" : "user", "id" : "stevekoch", "name" : "Steve Koch" }, "id" : "e/494128a2893e4bd2acac425b4e00518b/c/68661bf2db954075b7acbe1abcceae7e" }, { "date" : "2010-02-07T13:13:02Z", "body" : "Thanks for adding Steve. I think computational is more closely related to theoretical since there isn't a clear tradition of what constitutes an "experiment" and how to record it like there is in experimental sciences. I don't think the Wikipedia editors will allow the creation of a separate page just for examples of ONS but we certainly can put them at the end if some more examples get collected.", "from" : { "type" : "user", "id" : "jcbradley", "name" : "Jean-Claude Bradley" }, "id" : "e/494128a2893e4bd2acac425b4e00518b/c/8a86cef98b174b93a7962a0936e86ed8" }, { "date" : "2010-02-07T16:58:37Z", "body" : "I'm surprised that wikipedia editors have been harassing you, Jean-Claude! I've started many articles of questionable significance and never had anyone mark them for deletion. (For example: http://en.wikipedia.org/wiki...) Someday I think the article would have to be changed to "notable open notebook science practitioners," but I don't see why we couldn't have a "List of open notebook science practitioners" page. There are thousands of pages like that. For example: http://en.wikipedia.org/wiki...", "from" : { "type" : "user", "id" : "stevekoch", "name" : "Steve Koch" }, "id" : "e/494128a2893e4bd2acac425b4e00518b/c/988cd28e08804ad98dd9c8be0d9213ee" }, { "date" : "2010-02-07T17:02:44Z", "body" : "Carl, you should pipe in on whether your computational work is more similar to theory or experiment! I think the whole spectrum of science is much harder to put into categories than Jean-Claude or I expect. I see computational as "experiment" often. For example, I collaborate with some people doing molecular dynamics (MD) simulations. It surprising how much like experiments it is. Perhaps the best example (and most amusing to me when I learned it) was the need for a "thermostat" in the simulation. The student spent a few weeks tweaking the MD software until he could get his thermostat working. I'd say recording that process, along with all the failed experiments (and the conditions that led to them) would be very valuable. Very much like what we'd like to do in our experiments. But it's probably be easier to capture the information for the computational stuff--so I'd expect those open notebooks to be excellent sooner than ours.", "from" : { "type" : "user", "id" : "stevekoch", "name" : "Steve Koch" }, "id" : "e/494128a2893e4bd2acac425b4e00518b/c/54a9326944f047ebb57cbb715da68579" }, { "date" : "2010-02-07T18:20:44Z", "body" : "Steve - it was actually not that easy to get the ONS entry on Wikipedia to not be deleted or redirected - it took 2 tries and lots of documentation to appease the editors - see the discussion page. I guess you don't know how it will play out until you try.", "from" : { "type" : "user", "id" : "jcbradley", "name" : "Jean-Claude Bradley" }, "id" : "e/494128a2893e4bd2acac425b4e00518b/c/c8407558cee94d438d39b70b6a96354f" }, { "date" : "2010-02-07T18:32:07Z", "body" : "Sounds like an overly-aggressive guy was obsessed with deleting your article? No rush for anything, but if you think it'd be better with a sub-page of practitioners, I'll create the page someday.", "from" : { "type" : "user", "id" : "stevekoch", "name" : "Steve Koch" }, "id" : "e/494128a2893e4bd2acac425b4e00518b/c/c420da5c82fd404e926707be48698de4" }, { "date" : "2010-02-07T18:38:10Z", "body" : "Steve - I think it is actually much more difficult to capture the information for computational experiments because it is so easy to generate immense amounts of data. If every tweak is "an experiment" you would end up spending more time documenting what you do than actually doing work. When we did docking we did approach documenting it like a physical experiment so that there is enough information to reproduce (e.g. http://usefulchem.wikispaces.com/D-EXP01... ) but we didn't record every parameter tried. In a wet lab experiment the situation is much more clear cut - if you do something physically in the lab during an experiment you record it. This is a practice that is part of academia and industry - well defined enough that the "lab notebook" has a legal meaning in patent law.", "from" : { "type" : "user", "id" : "jcbradley", "name" : "Jean-Claude Bradley" }, "id" : "e/494128a2893e4bd2acac425b4e00518b/c/02d47d6331a34b2487c88a82746ae878" }, { "date" : "2010-02-07T19:11:08Z", "body" : "Interesting, Jean-Claude. And I hadn't been thinking of the legal definition (and I also don't feel like thinking about that now :) ). The MD simulations I was thinking of actually took significant time on a supercomputer for each tweak (I think). So, that would be practical to record everything and treat it as an experiment. Clearly, though, as you say there are cases where it would be very difficult to capture everything. This is true in some experiments, too, though! For example I remember in the Collider Detector Facility (CDF) at Fermilab, the first round of data acquisition was all hardware and the job was to filter out 90% (or whatever fraction) of the data so that the bandwidth of the next steps would be sufficient. That seems like a clear example of too much experimental data to save. So, probably the spectrum of open notebook science shouldn't just be one-dimensional from theory to experiment. It seems like at least one more dimension is needed which describes how much information there is to capture.", "from" : { "type" : "user", "id" : "stevekoch", "name" : "Steve Koch" }, "id" : "e/494128a2893e4bd2acac425b4e00518b/c/fbba7912ab354b0f83a39ddb3b20872d" }, { "date" : "2010-02-07T19:15:36Z", "body" : "And perhaps another dimension for how much tacit knowledge there is. I think tacit knowledge may be what I had in mind when I said computational science may be easier to do as ONS. Certainly there is tacit knowledge in computational science. But listening to John Hogenech at ScienceOnline2010, I learned that it's possible for one group to exactly replicate another group's computations, if they use Amazon Web Services as the platform. Or, Deepak pointed out Virtual Machines to me as a way of packaging a computational environment. So it seems easier to at least transfer some of the tacit knowledge. In a wetlab, it's still not possible to do that. So, maybe there're at least three dimensions on which to classify ONS: (1) experiment / theory, (2) volume of information, and (3) volume of tacit knowledge (or maybe ratio of tacit knowledge to explicit knowledge)", "from" : { "type" : "user", "id" : "stevekoch", "name" : "Steve Koch" }, "id" : "e/494128a2893e4bd2acac425b4e00518b/c/1eda8e01599d48ca8c0b616e147be298" }, { "date" : "2010-02-07T19:17:56Z", "body" : "For Andy's gliding motility assays in our lab, I'd rate it (1) solidly in experiment, (2) low/moderate amounts of information (GBs of image data), (3) moderate/high amounts of tacit knowledge. (Or tacit knowledge that is difficult to capture. Maybe that's what the 3rd dimension is: how difficult to capture the tacit knowledge)", "from" : { "type" : "user", "id" : "stevekoch", "name" : "Steve Koch" }, "id" : "e/494128a2893e4bd2acac425b4e00518b/c/01e7bfc210844a0ba7ff159c1b196759" }, { "date" : "2010-02-07T20:57:23Z", "body" : "Interesting discussion! In my mind they are both. In the phyologenetics notebook, I am trying to extend the theory of comparative methods beyond linear models. This field is moving very quickly, and it's no use to suggest new theory without providing software that implements it, or no one will be able to use it. I also find that saving all the data from all the runs I do can be prohibitive. If I want to repeat any simulation or run I describe in the notebook, I (or anyone else) can grab the code as it was that day from the subversion repository on google and rerun it. Still figuring out how to get the most out of this!", "from" : { "type" : "user", "id" : "cboettig", "name" : "Carl Boettiger" }, "id" : "e/494128a2893e4bd2acac425b4e00518b/c/6d8df0b1e9ae4e4dba415679585a7ddd" }, { "date" : "2010-02-08T14:38:56Z", "body" : "The reason I mention the legal definition of a lab notebook is that it leads to an expectation in the scientific community that students will be trained to record their experiments in a fairly consistent way. Perhaps I have the wrong impression here but it seems that there is not a standard way to record computational/theoretical work. [In fact as a postdoc I wanted to change the format of my lab notebook and my supervisor refused because it was not consistent with the requirements of our Research Office]. However, in general I think the acid test for a good notebook is whether an article or patent can be written from the records without significant interaction with the student/researcher who kept it. If the record keeping is so bad that one can't tell what happened in the experiment then the work is wasted. Unfortunately it isn't uncommon for students to repeat experiments from students who kept poor notes and left the lab.", "from" : { "type" : "user", "id" : "jcbradley", "name" : "Jean-Claude Bradley" }, "id" : "e/494128a2893e4bd2acac425b4e00518b/c/89ad7528242c4fe6af56e888adee3cbd" }, { "date" : "2010-02-08T14:43:49Z", "body" : "Carl - one of the benefits I'm finding from the researchers who keep Open Notebooks is learning how science is done in different fields and different groups. This is something that has traditionally been difficult to assess because notebooks are traditionally very private. Over time we're gathering data that will prove handy for discovering how the scientific process actually works - as opposed to the ideal of hypothesis -> experiment design and execution -> evaluation which is widely taught.", "from" : { "type" : "user", "id" : "jcbradley", "name" : "Jean-Claude Bradley" }, "id" : "e/494128a2893e4bd2acac425b4e00518b/c/e25821f4473a497396c8fb2ffe959bb4" }, { "date" : "2010-02-08T18:02:53Z", "body" : "Jean-Claude, that's an excellent point. I've also found that most of my colleagues in wet labs are taught to keep lab notebooks in a rather precise way. I know of only a few theorists in my department who keep any kind of regular notebook, and I've never had that kind of instruction or even encouragement. In computational sciences I'm surprised how few scientists use version management like subversion, which maintains a revision log, etc, for their codes. It will be interesting to see what feedback & suggestions I get on how to keep a notebook effectively.", "from" : { "type" : "user", "id" : "cboettig", "name" : "Carl Boettiger" }, "id" : "e/494128a2893e4bd2acac425b4e00518b/c/7c43664bf50e4e8e91eadd7a229fbf74" }, { "date" : "2010-02-08T20:28:06Z", "body" : "Thanks for the feedback Carl - it will be interesting to see what response you get", "from" : { "type" : "user", "id" : "jcbradley", "name" : "Jean-Claude Bradley" }, "id" : "e/494128a2893e4bd2acac425b4e00518b/c/b43bd571412644a4aeb1cfbdb4ae6fac" } ], "to" : [ { "type" : "user", "id" : "stevekoch", "name" : "Steve's feed" }, { "type" : "group", "id" : "science-2-0", "name" : "Science 2.0" }, { "type" : "group", "id" : "the-life-scientists", "name" : "The Life Scientists" }, { "type" : "group", "name" : "OpenWetWare", "id" : "oww" } ], "likes" : [ { "date" : "2010-02-10T10:07:47Z", "from" : { "type" : "user", "id" : "alethea", "name" : "Heather" } }, { "date" : "2010-02-08T16:08:57Z", "from" : { "type" : "user", "id" : "msscha", "name" : "Mickey Schafer" } }, { "date" : "2010-02-07T18:30:05Z", "from" : { "type" : "user", "id" : "imabonehead", "private" : true, "name" : "imabonehead" } }, { "date" : "2010-02-06T19:48:13Z", "from" : { "type" : "user", "id" : "graymills", "name" : "Peter Miller" } }, { "date" : "2010-02-06T18:26:48Z", "from" : { "type" : "user", "id" : "pfanderson", "name" : "Patricia F. Anderson" } }, { "date" : "2010-02-06T15:25:30Z", "from" : { "type" : "user", "id" : "danielmietchen", "name" : "Daniel Mietchen" } }, { "date" : "2010-02-06T14:23:09Z", "from" : { "type" : "user", "id" : "band", "name" : "Bill Anderson" } }, { "date" : "2010-02-06T14:20:14Z", "from" : { "type" : "user", "id" : "jcbradley", "name" : "Jean-Claude Bradley" } }, { "date" : "2010-02-06T11:11:24Z", "from" : { "type" : "user", "id" : "paulsb", "private" : true, "name" : "Paul Bacchus" } }, { "date" : "2010-02-06T05:56:58Z", "from" : { "type" : "user", "id" : "mrgunn", "name" : "Mr. Gunn" } }, { "date" : "2010-02-05T21:00:22Z", "from" : { "type" : "user", "id" : "billhooker", "name" : "Bill Hooker" } }, { "date" : "2010-02-05T19:45:51Z", "from" : { "type" : "user", "id" : "cboettig", "name" : "Carl Boettiger" } }, { "date" : "2010-02-05T19:44:41Z", "from" : { "type" : "user", "id" : "michaelnielsen", "name" : "Michael Nielsen" } }, { "date" : "2010-02-05T19:31:15Z", "from" : { "type" : "user", "id" : "treeoflife", "name" : "Jonathan Eisen" } } ], "date" : "2010-02-05T19:20:24Z", "feed_id" : "oww", "feed_name" : "OpenWetWare", "feed_description" : "Share your science", "feed_type" : "group" },{ "_id" : "e/64cdcfe1a4ec49d1adfeffeffc2ff6ad", "body" : "Moving more of my lab notes to OpenWetWare. Problem: Most previous notes contain screenshots of copyrighted materials. How to deal with that? Notebook much less useful without these.", "from" : { "type" : "user", "id" : "danielmietchen", "name" : "Daniel Mietchen" }, "url" : "http://friendfeed.com/science-2-0/64cdcfe1/moving-more-of-my-lab-notes-to-openwetware", "comments" : [ { "date" : "2010-02-08T13:20:55Z", "body" : "What are they screenshots of? If it's shots of analysis software I don't think anyone is too likely to go after you. Small snippets of things should be ok as well. Your bigger problem may actually be uploading lots of images...", "from" : { "type" : "user", "id" : "cameronneylon", "name" : "Cameron Neylon" }, "id" : "e/64cdcfe1a4ec49d1adfeffeffc2ff6ad/c/dfaea14345454abd9cf0ee6a034b06b7" }, { "date" : "2010-02-08T20:27:31Z", "body" : "The screenshots are of basically anything you can find in papers - figures, tables, equations, quotes, text or combinations thereof. Several hundreds of them, named in a way that scripts could handle them. Is bot upload allowed on OWW?", "from" : { "type" : "user", "id" : "danielmietchen", "name" : "Daniel Mietchen" }, "id" : "e/64cdcfe1a4ec49d1adfeffeffc2ff6ad/c/6a10ce45266541adaba1c78ea9a8310b" }, { "date" : "2010-02-08T20:47:43Z", "body" : "@Daniel, no, the OWW API ( http://openwetware.org/api.php . ) is read only", "from" : { "type" : "user", "id" : "yokofakun", "name" : "Pierre Lindenbaum" }, "id" : "e/64cdcfe1a4ec49d1adfeffeffc2ff6ad/c/a80cab922b064517b6de105881fcbe52" }, { "date" : "2010-02-08T21:03:57Z", "body" : "Thanks, Pierre. That's not what I had hoped for, but it shall facilitate further planning. Perhaps it's best just to let the current projects run out on their old platform and to start new ones in the open (if the coworkers agree, which is not always a given).", "from" : { "type" : "user", "id" : "danielmietchen", "name" : "Daniel Mietchen" }, "id" : "e/64cdcfe1a4ec49d1adfeffeffc2ff6ad/c/a8198dba921e40c3a23fad756f68a1b1" }, { "date" : "2010-02-08T21:13:45Z", "body" : "Well, may be you can ask OWW to turn on the write API. ( http://www.mediawiki.org/wiki... )", "from" : { "type" : "user", "id" : "yokofakun", "name" : "Pierre Lindenbaum" }, "id" : "e/64cdcfe1a4ec49d1adfeffeffc2ff6ad/c/b20d4a34f8d84aa9acb8d46d4406c01a" }, { "date" : "2010-02-08T23:02:58Z", "body" : "Thanks, will give it a try.", "from" : { "type" : "user", "id" : "danielmietchen", "name" : "Daniel Mietchen" }, "id" : "e/64cdcfe1a4ec49d1adfeffeffc2ff6ad/c/c4fce70eb47f4727a46dd4716c25f3c7" }, { "date" : "2010-02-09T01:51:41Z", "body" : "Daniel - when we refer to other papers in our notebooks we link to the DOI. For ILL requests we upload them to a password protected server where all of our collaborators know the password. For full non-OA papers I don't think we have a choice on the matter. But for single figures or quotes I think you can make a good case for fair use and make them public. We do that routinely. You are not trying to sell copyrighted material so I think the worst case would be the publisher finding your image and requesting you to take it down - and we have not come across that problem. Good luck with getting your co-workers to agree!", "from" : { "type" : "user", "id" : "jcbradley", "name" : "Jean-Claude Bradley" }, "id" : "e/64cdcfe1a4ec49d1adfeffeffc2ff6ad/c/1d80a4426a8b4f4ebc4247743ffcab9d" }, { "date" : "2010-02-09T13:16:04Z", "body" : "I am now uploading some of the files to flickr to see whether that could be an alternative.", "from" : { "type" : "user", "id" : "danielmietchen", "name" : "Daniel Mietchen" }, "id" : "e/64cdcfe1a4ec49d1adfeffeffc2ff6ad/c/b82b38779ca94272af0f33d247c1a2d7" }, { "date" : "2010-02-09T14:40:59Z", "body" : "We have used Flickr - but usually just upload images to Wikispaces since they automatically get included in the archive when doing an HTML export of the entire wiki. Does OWW have export options for back-ups?", "from" : { "type" : "user", "id" : "jcbradley", "name" : "Jean-Claude Bradley" }, "id" : "e/64cdcfe1a4ec49d1adfeffeffc2ff6ad/c/bf3b90215c644f4da6123d2a34ad8fa1" }, { "date" : "2010-02-09T14:45:19Z", "body" : "I agree if you have small bits you can claim fair use, especially if you are using the material for academic purposes. You can also alter an image, graph, or figure and attribute it as an adaptation from the original with a link it it.", "from" : { "type" : "user", "id" : "eabrown25", "name" : "Elizabeth Brown" }, "id" : "e/64cdcfe1a4ec49d1adfeffeffc2ff6ad/c/c75d7a381f2340d0afedb4af0faf5387" } ], "to" : [ { "type" : "user", "id" : "danielmietchen", "name" : "Daniel's feed" }, { "type" : "group", "id" : "science-2-0", "name" : "Science 2.0" }, { "type" : "group", "name" : "OpenWetWare", "id" : "oww" } ], "likes" : [ { "date" : "2010-02-09T01:43:15Z", "from" : { "type" : "user", "id" : "jcbradley", "name" : "Jean-Claude Bradley" } } ], "date" : "2010-02-08T12:57:29Z", "feed_id" : "oww", "feed_name" : "OpenWetWare", "feed_description" : "Share your science", "feed_type" : "group" },{ "_id" : "e/904424cccfe84291a7ce7a481407f64b", "body" : "Can someone explain to me how the stats counter at the bottom of the OpenWetWare page works? Is it total visits or unique ips? Is there any way to get more detailed stats (i.e. like google analytics for a webpage?) I think it would be interesting to know how people come across my notebook, from where, etc.", "from" : { "type" : "user", "id" : "cboettig", "name" : "Carl Boettiger" }, "url" : "http://friendfeed.com/oww/904424cc/can-someone-explain-to-me-how-stats-counter-at", "comments" : [ { "date" : "2010-02-09T09:22:49Z", "body" : "I guess it is the count of visits ( http://www.mediawiki.org/wiki... ). An extension for Google analytics is available: http://www.mediawiki.org/wiki...", "from" : { "type" : "user", "id" : "yokofakun", "name" : "Pierre Lindenbaum" }, "id" : "e/904424cccfe84291a7ce7a481407f64b/c/346568ba785244d29b65e0f76775bf35" }, { "date" : "2010-02-09T09:29:16Z", "body" : "Looks like the OpenWetWare maintainers would have to install the google analytics extension first?", "from" : { "type" : "user", "id" : "cboettig", "name" : "Carl Boettiger" }, "id" : "e/904424cccfe84291a7ce7a481407f64b/c/3c3f7f19a7704e57a8b0028984f3b817" }, { "date" : "2010-02-09T09:33:17Z", "body" : "Installing an extension shouldn't be a problem. OWW already contains many extensions http://openwetware.org/wiki...", "from" : { "type" : "user", "id" : "yokofakun", "name" : "Pierre Lindenbaum" }, "id" : "e/904424cccfe84291a7ce7a481407f64b/c/db8734ccb0e8472a8f4b631a18a6deff" }, { "date" : "2010-03-08T23:41:30Z", "body" : "Google Analytics is good for long term tracking. We also use Sitemeter, which is a handy way of letting anyone publicly track the last 100 visitors and seeing the keywords they used (hit by referrals from the sitemeter icon in the nav bar for example http://onschallenge.wikispaces.com/ )", "from" : { "type" : "user", "id" : "jcbradley", "name" : "Jean-Claude Bradley" }, "id" : "e/904424cccfe84291a7ce7a481407f64b/c/372b5f1607e744358acd2e1ef03014d8" } ], "to" : [ { "type" : "group", "name" : "OpenWetWare", "id" : "oww" } ], "date" : "2010-02-09T09:13:10Z", "feed_id" : "oww", "feed_name" : "OpenWetWare", "feed_description" : "Share your science", "feed_type" : "group" },{ "_id" : "e/b44ce050372e4620a8f2d1bee0e6b028", "body" : "Working with some other students to start an Open Science group at UC Davis to help raise awareness, share tools, build community and pressure for more open science on campus. Anyone know of such groups elsewhere that could be a model? Anyone have experience doing so?", "from" : { "type" : "user", "id" : "cboettig", "name" : "Carl Boettiger" }, "url" : "http://friendfeed.com/sciencecommons/b44ce050/working-with-some-other-students-to-start-open", "comments" : [ { "date" : "2010-02-23T21:53:25Z", "body" : "UC Davis has an excellent group of science librarians (at least in the physical sciences - don't know the bio folks individually) - you should e-mail them and ask for help. You could start by e-mailing: pse@lib.ucdavis.edu", "from" : { "type" : "user", "id" : "cpikas", "name" : "Christina Pikas" }, "id" : "e/b44ce050372e4620a8f2d1bee0e6b028/c/ab3c0aa6ec574692bd1a6ad936ce1dae" }, { "date" : "2010-02-23T23:21:07Z", "body" : "I think the people in the groups of Jean-Claude Bradley, Matthew Todd or Steve Koch would be a good pool to dive in.", "from" : { "type" : "user", "id" : "danielmietchen", "name" : "Daniel Mietchen" }, "id" : "e/b44ce050372e4620a8f2d1bee0e6b028/c/b34c18cfefa746e7b9c1ad15c321aa50" }, { "date" : "2010-02-24T04:53:27Z", "body" : "Thanks for the mention, Daniel. Carl, check out The Synaptic Leap for our current project. http://www.thesynapticleap.org/schisto...", "from" : { "type" : "user", "id" : "mattodd", "name" : "Matthew Todd" }, "id" : "e/b44ce050372e4620a8f2d1bee0e6b028/c/6427b85c5043486da38664a04b08c63e" }, { "date" : "2010-02-24T05:04:42Z", "body" : "Matthew, that looks excellent. I remember seeing that in Nature news earlier this month! Great to see the website for the project. Will be a good example to share with other students.", "from" : { "type" : "user", "id" : "cboettig", "name" : "Carl Boettiger" }, "id" : "e/b44ce050372e4620a8f2d1bee0e6b028/c/d2d143d0e2b1471faf9948cca64ff54e" }, { "date" : "2010-03-07T17:12:01Z", "body" : "Carl, I don't have a clear vision of what you should do ... but I agree with Daniel that connecting with students elsewhere would be great. Let me know if you want to get in touch with people in our lab.", "from" : { "type" : "user", "id" : "stevekoch", "name" : "Steve Koch" }, "id" : "e/b44ce050372e4620a8f2d1bee0e6b028/c/cfa68513a2754d6c9863edb3ebe0dbb8" }, { "date" : "2010-03-08T16:19:57Z", "body" : "I'm not sure if you are talking about students in research or teaching labs but Steve has great examples of both. I have more experience with students in research labs.and we can both recommend tools.", "from" : { "type" : "user", "id" : "jcbradley", "name" : "Jean-Claude Bradley" }, "id" : "e/b44ce050372e4620a8f2d1bee0e6b028/c/9eaf08b0f6f7451085115ef56655b8f8" }, { "date" : "2010-03-08T21:27:36Z", "body" : "Really aiming to organize students, staff, faculty across campus to promote an on-campus dialog about open science, similar to the on-line dialog that happens here. Our goals are to share tools, build community and advocate/promote more open science. We're getting underway now: http://openwetware.org/wiki...", "from" : { "type" : "user", "id" : "cboettig", "name" : "Carl Boettiger" }, "id" : "e/b44ce050372e4620a8f2d1bee0e6b028/c/d0abab27e1314845b8788b02d7f4815b" }, { "date" : "2010-03-08T23:45:29Z", "body" : "Carl, if you are using OWW Steve is your man. If you are going to be serving a group of users you might want to consider automatically archiving their datasets. A very convenient way of hosting Open Data is through Google Spreadsheets. Andrew Lang has written some code to automatically archive these as Excel by crawling through HTML pages. See for more info: http://usefulchem.blogspot.com/2010...", "from" : { "type" : "user", "id" : "jcbradley", "name" : "Jean-Claude Bradley" }, "id" : "e/b44ce050372e4620a8f2d1bee0e6b028/c/972d6ccc4d4a4f37871a974e5b2fd143" } ], "to" : [ { "type" : "user", "id" : "cboettig", "name" : "Carl's feed" }, { "type" : "group", "id" : "sciencecommons", "name" : "Science Commons" }, { "type" : "group", "id" : "scienceonline2012", "name" : "ScienceOnline2012" }, { "type" : "group", "id" : "science-2-0", "name" : "Science 2.0" }, { "type" : "group", "id" : "the-life-scientists", "name" : "The Life Scientists" }, { "type" : "group", "name" : "OpenWetWare", "id" : "oww" } ], "likes" : [ { "date" : "2010-03-09T07:29:55Z", "from" : { "type" : "user", "id" : "suelibrarian", "private" : true, "name" : "suelibrarian" } }, { "date" : "2010-03-09T00:14:16Z", "from" : { "type" : "user", "id" : "gezelter", "name" : "Dan Gezelter" } }, { "date" : "2010-03-08T17:31:26Z", "from" : { "type" : "user", "id" : "researchremix", "name" : "Heather Piwowar" } }, { "date" : "2010-03-08T16:53:34Z", "from" : { "type" : "user", "id" : "krash63", "private" : true, "name" : "Kristi Miller Durazo" } }, { "date" : "2010-03-08T16:51:01Z", "from" : { "type" : "user", "id" : "attilacsordas", "name" : "Attila Csordas" } }, { "date" : "2010-03-08T16:21:27Z", "from" : { "type" : "user", "id" : "khalidmirza", "name" : "Khalid Mirza" } }, { "date" : "2010-03-08T16:16:35Z", "from" : { "type" : "user", "id" : "jcbradley", "name" : "Jean-Claude Bradley" } }, { "date" : "2010-03-07T17:10:30Z", "from" : { "type" : "user", "id" : "stevekoch", "name" : "Steve Koch" } }, { "date" : "2010-02-24T06:17:19Z", "from" : { "type" : "user", "id" : "mrgunn", "name" : "Mr. Gunn" } }, { "date" : "2010-02-24T06:00:02Z", "from" : { "type" : "user", "id" : "brembs", "name" : "Björn Brembs" } }, { "date" : "2010-02-24T04:53:32Z", "from" : { "type" : "user", "id" : "mattodd", "name" : "Matthew Todd" } }, { "date" : "2010-02-24T01:42:01Z", "from" : { "type" : "user", "id" : "dgaston", "name" : "Daniel Gaston" } }, { "date" : "2010-02-24T01:03:29Z", "from" : { "type" : "user", "id" : "scimatic", "name" : "Jamie McQuay" } }, { "date" : "2010-02-23T23:56:14Z", "from" : { "type" : "user", "id" : "billhooker", "name" : "Bill Hooker" } }, { "date" : "2010-02-23T23:20:54Z", "from" : { "type" : "user", "id" : "danielmietchen", "name" : "Daniel Mietchen" } }, { "date" : "2010-02-23T22:44:47Z", "from" : { "type" : "user", "id" : "plausibleaccuracy", "name" : "Jason Winget" } }, { "date" : "2010-02-23T21:58:03Z", "from" : { "type" : "user", "id" : "cpikas", "name" : "Christina Pikas" } } ], "date" : "2010-02-23T21:20:56Z", "feed_id" : "oww", "feed_name" : "OpenWetWare", "feed_description" : "Share your science", "feed_type" : "group" },{ "_id" : "e/2a4af18d6f02454aa6e5b65db896ae5c", "body" : "<biblio> error at OWW: Where to report such things? Example: http://openwetware.org/wiki... (currently gives "Error fetching PMID 19123244", while other papers seem unaffected).", "from" : { "type" : "user", "id" : "danielmietchen", "name" : "Daniel Mietchen" }, "url" : "http://friendfeed.com/oww/2a4af18d/biblio-error-at-oww-where-to-report-such-things", "comments" : [ { "date" : "2010-04-29T09:46:52Z", "body" : "Even worse at http://openwetware.org/wiki... , where only one displays properly. Both pages had no problems last time I checked.", "from" : { "type" : "user", "id" : "danielmietchen", "name" : "Daniel Mietchen" }, "id" : "e/2a4af18d6f02454aa6e5b65db896ae5c/c/b888433991d14a8da4c44edb6146b9aa" }, { "date" : "2010-04-29T09:50:05Z", "body" : "send a mail to Bill Flanagan http://openwetware.org/wiki...", "from" : { "type" : "user", "id" : "yokofakun", "name" : "Pierre Lindenbaum" }, "id" : "e/2a4af18d6f02454aa6e5b65db896ae5c/c/8b6776485d434da9b67699f602a8fb8f" }, { "date" : "2010-04-29T10:08:51Z", "body" : "Done - thanks!", "from" : { "type" : "user", "id" : "danielmietchen", "name" : "Daniel Mietchen" }, "id" : "e/2a4af18d6f02454aa6e5b65db896ae5c/c/acdd290683e24c1abdbc00564fc42873" } ], "to" : [ { "type" : "group", "name" : "OpenWetWare", "id" : "oww" } ], "date" : "2010-04-29T09:46:23Z", "feed_id" : "oww", "feed_name" : "OpenWetWare", "feed_description" : "Share your science", "feed_type" : "group" },{ "_id" : "e/7079cc6f63db412fb697c72dc1d445a0", "body" : "First go at a brainstorming session from this morning. http://prezi.com/0qg1e6f... Any comments more than welcome!", "from" : { "type" : "user", "id" : "kubke", "name" : "Kubke" }, "url" : "http://friendfeed.com/oww/7079cc6f/first-go-at-brainstorming-session-from-this", "comments" : [ { "date" : "2010-07-10T08:09:00Z", "body" : ""There is no Prezi on this address, or it has not been published."", "from" : { "type" : "user", "id" : "danielmietchen", "name" : "Daniel Mietchen" }, "id" : "e/7079cc6f63db412fb697c72dc1d445a0/c/cc2f3fefa04b4029923d81511d6cce03" }, { "date" : "2010-07-10T12:28:32Z", "body" : "Oops... forgot that the default was 'private'. It is public now :)", "from" : { "type" : "user", "id" : "kubke", "name" : "Kubke" }, "id" : "e/7079cc6f63db412fb697c72dc1d445a0/c/df827637385040f69930bb3e448c7e2f" }, { "date" : "2010-07-12T14:32:34Z", "body" : "Nothing happens when you click on the play/next slide button.", "from" : { "type" : "user", "id" : "maverickny", "name" : "Sally Church" }, "id" : "e/7079cc6f63db412fb697c72dc1d445a0/c/2ab658cb7e2f49c1ab172b1542a9a9ef" }, { "date" : "2010-07-12T21:24:59Z", "body" : "OK, I will try to put this somewhere else. Sorry about that....", "from" : { "type" : "user", "id" : "kubke", "name" : "Kubke" }, "id" : "e/7079cc6f63db412fb697c72dc1d445a0/c/491e6635803f42dfb46b3db71f33c474" }, { "date" : "2011-04-06T10:12:07Z", "body" : "Redone http://wikieducator.org/images...", "from" : { "type" : "user", "id" : "kubke", "name" : "Kubke" }, "id" : "e/7079cc6f63db412fb697c72dc1d445a0/c/0422bc89d1ff4d0da7542c93cad9ceaf" }, { "date" : "2011-04-06T13:27:57Z", "body" : "maybe link society and policy with a double arrow?", "from" : { "type" : "user", "id" : "claudiakoltzenburg", "name" : "Claudia Koltzenburg" }, "id" : "e/7079cc6f63db412fb697c72dc1d445a0/c/f6f3e7551f53422191bf38a328fb9cc7" }, { "date" : "2011-04-06T13:31:44Z", "body" : "I thought about it.. but does society influence policy directly or through their elected representatives? (policy has to be gov mediated, doesn't it?)", "from" : { "type" : "user", "id" : "kubke", "name" : "Kubke" }, "id" : "e/7079cc6f63db412fb697c72dc1d445a0/c/2dd8f957cf3547c9930e993c0e63f214" }, { "date" : "2011-04-06T13:35:25Z", "body" : "But - perhaps there should be arrows from society to education (parents are on governing boards), to health (hospital volunteering, red cross) and to science (citizen science) (updated)", "from" : { "type" : "user", "id" : "kubke", "name" : "Kubke" }, "id" : "e/7079cc6f63db412fb697c72dc1d445a0/c/381c43b98e1a4d219b6ae9ae1482f67c" } ], "to" : [ { "type" : "user", "id" : "kubke", "name" : "Kubke's feed" }, { "type" : "group", "name" : "OpenWetWare", "id" : "oww" }, { "type" : "group", "id" : "science-2-0", "name" : "Science 2.0" }, { "type" : "group", "id" : "future-of-education", "name" : "Future of Education" }, { "type" : "group", "id" : "the-life-scientists", "name" : "The Life Scientists" } ], "date" : "2010-07-10T05:42:43Z", "feed_id" : "oww", "feed_name" : "OpenWetWare", "feed_description" : "Share your science", "feed_type" : "group" },{ "_id" : "e/0f6575ddc2714ad8850b7ebbf344d9ff", "body" : "OpenWetWare - MediaWiki Widgets - http://www.mediawikiwidgets.org/OpenWet...", "via" : { "url" : "http://friendfeed.com/share/bookmarklet", "name" : "Bookmarklet" }, "from" : { "type" : "user", "id" : "danielmietchen", "name" : "Daniel Mietchen" }, "url" : "http://friendfeed.com/oww/0f6575dd/openwetware-mediawiki-widgets", "comments" : [ { "date" : "2010-08-17T13:01:32Z", "body" : ""This widget allows you to embed OpenWetWare pages on your wiki page."", "via" : { "url" : "http://friendfeed.com/share/bookmarklet", "name" : "Bookmarklet" }, "from" : { "type" : "user", "id" : "danielmietchen", "name" : "Daniel Mietchen" }, "id" : "e/0f6575ddc2714ad8850b7ebbf344d9ff/c/bab2984b4b844d2cadea6bceef5b30e3" }, { "date" : "2010-08-18T23:29:47Z", "body" : "Just wanted to play a bit more with it, but OWW is down right now.", "from" : { "type" : "user", "id" : "danielmietchen", "name" : "Daniel Mietchen" }, "id" : "e/0f6575ddc2714ad8850b7ebbf344d9ff/c/12f5d586194c450887ed8ee61141b2a3" }, { "date" : "2010-08-19T23:45:34Z", "body" : "OpenWetWare is back!", "from" : { "type" : "user", "id" : "danielmietchen", "name" : "Daniel Mietchen" }, "id" : "e/0f6575ddc2714ad8850b7ebbf344d9ff/c/d224ea67f60f448e9a8d2224941a2096" } ], "to" : [ { "type" : "user", "id" : "danielmietchen", "name" : "Daniel's feed" }, { "type" : "group", "name" : "OpenWetWare", "id" : "oww" }, { "type" : "group", "id" : "scholarly-wikis", "name" : "Scholarly wikis" } ], "likes" : [ { "date" : "2010-08-17T13:13:24Z", "from" : { "type" : "user", "id" : "yokofakun", "name" : "Pierre Lindenbaum" } } ], "date" : "2010-08-17T13:01:32Z", "feed_id" : "oww", "feed_name" : "OpenWetWare", "feed_description" : "Share your science", "feed_type" : "group" },{ "_id" : "e/3adcbac67dab409bb5dab59866c30a13", "body" : "OpenWetWare tips and reflections. Comments welcome. http://www.openwetware.org/wiki...", "from" : { "type" : "user", "id" : "researchremix", "name" : "Heather Piwowar" }, "url" : "http://friendfeed.com/oww/3adcbac6/openwetware-tips-and-reflections-comments", "comments" : [ { "date" : "2010-08-18T19:56:14Z", "body" : "Great review, I agree with both the strengths and weaknesses you've listed. What's troubled me most is (a) the full-text search functions don't seem to completely index my notebook, (b) Categories just aren't sufficient for tagging, and (b) offline updates syncing doesn't work (despite trying the mediawiki app) . The best features are the community (though small), calendar, embedding, and template format (cover page, summary, updates).", "from" : { "type" : "user", "id" : "cboettig", "name" : "Carl Boettiger" }, "id" : "e/3adcbac67dab409bb5dab59866c30a13/c/54dd828890fd4b12856f6e985172fecb" } ], "to" : [ { "type" : "user", "id" : "researchremix", "name" : "Heather's feed" }, { "type" : "group", "name" : "OpenWetWare", "id" : "oww" } ], "likes" : [ { "date" : "2010-08-23T15:57:58Z", "from" : { "type" : "user", "id" : "pampel1", "name" : "Heinz Pampel" } }, { "date" : "2010-08-18T21:12:48Z", "from" : { "type" : "user", "id" : "kubke", "name" : "Kubke" } }, { "date" : "2010-08-18T19:49:44Z", "from" : { "type" : "user", "id" : "cboettig", "name" : "Carl Boettiger" } } ], "date" : "2010-08-18T19:31:58Z", "feed_id" : "oww", "feed_name" : "OpenWetWare", "feed_description" : "Share your science", "feed_type" : "group" },{ "_id" : "e/e5057a549af34d5e902c941a19f6473d", "body" : "Yikes, is openwetware.org down? Looks like it is: http://downforeveryoneorjustme.com/openwet...", "from" : { "type" : "user", "id" : "researchremix", "name" : "Heather Piwowar" }, "url" : "http://friendfeed.com/oww/e5057a54/yikes-is-openwetware-org-down-looks-like-it", "comments" : [ { "date" : "2010-08-18T20:40:11Z", "body" : "and I was about to comment a tool for at least downloading openwetware sites for working offline, but of course I've forgotten the name and it's written in my notebook! hmm.. seriously considering migrating my lab notebooks github's updated wiki, hope those 300mb are truly a soft limit...", "from" : { "type" : "user", "id" : "cboettig", "name" : "Carl Boettiger" }, "id" : "e/e5057a549af34d5e902c941a19f6473d/c/fa77a5acb83a476dbe41518a7a9c99bc" }, { "date" : "2010-08-18T20:53:54Z", "body" : "yup, I've started an open notebook there and it is working really well so far. I miss the OWW embedding though!", "from" : { "type" : "user", "id" : "researchremix", "name" : "Heather Piwowar" }, "id" : "e/e5057a549af34d5e902c941a19f6473d/c/a298c5251edc46a7b80205319464f52f" }, { "date" : "2010-08-18T21:10:01Z", "body" : "neat. Embedding seems to work for me: http://wiki.github.com/cboetti...", "from" : { "type" : "user", "id" : "cboettig", "name" : "Carl Boettiger" }, "id" : "e/e5057a549af34d5e902c941a19f6473d/c/378a924f8c3749f28fbac883e67ad7cd" }, { "date" : "2010-08-18T21:16:39Z", "body" : "No such luck for me on my test page here http://github.com/hpiwowa... I cut and paste your code. It looks like you haven't upgraded your wiki yet to the git-backed rewerite? I wonder if that would make a difference? Or am I just doing something silly wrong?", "from" : { "type" : "user", "id" : "researchremix", "name" : "Heather Piwowar" }, "id" : "e/e5057a549af34d5e902c941a19f6473d/c/f84125d9033340d28aaa525381a2e515" }, { "date" : "2010-08-18T21:27:38Z", "body" : "hmm, no, realized i hadn't upgraded that one. hmm", "from" : { "type" : "user", "id" : "cboettig", "name" : "Carl Boettiger" }, "id" : "e/e5057a549af34d5e902c941a19f6473d/c/f3b58936e630457f86d6d1dc97b45c98" } ], "to" : [ { "type" : "user", "id" : "researchremix", "name" : "Heather's feed" }, { "type" : "group", "name" : "OpenWetWare", "id" : "oww" } ], "likes" : [ { "date" : "2010-08-19T15:25:48Z", "from" : { "type" : "user", "id" : "danielmietchen", "name" : "Daniel Mietchen" } } ], "date" : "2010-08-18T20:04:56Z", "feed_id" : "oww", "feed_name" : "OpenWetWare", "feed_description" : "Share your science", "feed_type" : "group" },{ "_id" : "e/a40f65e185334628b027c9f85036a7d2", "body" : "Fwd: Really need openwetware back up! Drew Endy is working on it... time to start keeping a local clone? (via http://friendfeed.com/cboetti...)", "from" : { "type" : "user", "id" : "cboettig", "name" : "Carl Boettiger" }, "url" : "http://friendfeed.com/oww/a40f65e1/fwd-really-need-openwetware-back-up-drew-endy-is", "to" : [ { "type" : "group", "name" : "OpenWetWare", "id" : "oww" } ], "date" : "2010-08-19T17:31:31Z", "feed_id" : "oww", "feed_name" : "OpenWetWare", "feed_description" : "Share your science", "feed_type" : "group" },{ "_id" : "e/7d66ccd6095f454cbddfdf9a7aac5f25", "body" : "OpenWetWare back up!", "from" : { "type" : "user", "id" : "cboettig", "name" : "Carl Boettiger" }, "url" : "http://friendfeed.com/oww/7d66ccd6/openwetware-back-up", "to" : [ { "type" : "user", "id" : "cboettig", "name" : "Carl's feed" }, { "type" : "group", "name" : "OpenWetWare", "id" : "oww" } ], "likes" : [ { "date" : "2010-08-19T18:42:07Z", "from" : { "type" : "user", "id" : "researchremix", "name" : "Heather Piwowar" } } ], "date" : "2010-08-19T18:25:29Z", "feed_id" : "oww", "feed_name" : "OpenWetWare", "feed_description" : "Share your science", "feed_type" : "group" },{ "_id" : "e/e9d9b6addc474337ab1e65b1ef63e949", "body" : "I'm looking for a good solution to upload figures into my open lab notebook. Need fast, many photo, automated / scriptable uploading, permanent hosting, with searching/tags/comments. Trying photobucket: http://openwetware.org/wiki... Thoughts?", "from" : { "type" : "user", "id" : "cboettig", "name" : "Carl Boettiger" }, "url" : "http://friendfeed.com/science-2-0/e9d9b6ad/i-m-looking-for-good-solution-to-upload-figures", "comments" : [ { "date" : "2010-08-30T19:04:13Z", "body" : "I think ideally I would run a script which would run some code which generates a png figure, pushes the photo to the host site under a given album/tags and a link to the version of the code that created the figure on the project's github site. Since the codes take a long time to run, simply having the code version is no longer sufficient for me.", "from" : { "type" : "user", "id" : "cboettig", "name" : "Carl Boettiger" }, "id" : "e/e9d9b6addc474337ab1e65b1ef63e949/c/e62f6d5af4604d87951c6def53e6f5f0" }, { "date" : "2010-08-30T19:21:04Z", "body" : "Have you considered the possibility of using Flickr to host the photos? They have an API, are quite inexpensive and I know that there is/was a plugin to add Flickr images easily into OWW (mediawiki).", "from" : { "type" : "user", "id" : "rvidal", "name" : "Ricardo Vidal" }, "id" : "e/e9d9b6addc474337ab1e65b1ef63e949/c/36b0e32c659947dcb3b1f7a029b6fb9a" }, { "date" : "2010-08-30T19:27:40Z", "body" : "Yup, Flickr seems very promising since there's lots of development around it. Do I need to buy a subscription to make sure the uploads are permanent? Think I'll give it a try...", "from" : { "type" : "user", "id" : "cboettig", "name" : "Carl Boettiger" }, "id" : "e/e9d9b6addc474337ab1e65b1ef63e949/c/2814c3af84ba4ae5ad2ca95f30d27202" }, { "date" : "2010-08-30T19:57:34Z", "body" : "No, all uploads are permanent and I believe you can "display" up to 200 images for free. The last 200 are always visible and nothing is lost. If you pay the $24 USD/year, all images become public/visible again.", "from" : { "type" : "user", "id" : "rvidal", "name" : "Ricardo Vidal" }, "id" : "e/e9d9b6addc474337ab1e65b1ef63e949/c/5da1a835461e4544837d4be60a9cf58d" }, { "date" : "2010-08-30T23:15:10Z", "body" : "Flickr seems to be a nice solution. With one command-line call I can have a full slideshow of results embedded into the notebook! http://openwetware.org/wiki... Each image can collect comments and other tags and be organized into groups. the command-line upload also doesn't seem to spam my FF/twitter feed even though I added flickr to FF. guess that's a good thing.", "from" : { "type" : "user", "id" : "cboettig", "name" : "Carl Boettiger" }, "id" : "e/e9d9b6addc474337ab1e65b1ef63e949/c/cb39fe5ed7434f9f814115e71f99ea7f" } ], "to" : [ { "type" : "group", "id" : "science-2-0", "name" : "Science 2.0" }, { "type" : "group", "id" : "the-life-scientists", "name" : "The Life Scientists" }, { "type" : "group", "name" : "OpenWetWare", "id" : "oww" }, { "type" : "group", "id" : "sciencecommons", "name" : "Science Commons" } ], "likes" : [ { "date" : "2010-08-31T14:36:50Z", "from" : { "type" : "user", "id" : "paulsb", "private" : true, "name" : "Paul Bacchus" } }, { "date" : "2010-08-31T00:55:31Z", "from" : { "type" : "user", "id" : "stevekoch", "name" : "Steve Koch" } }, { "date" : "2010-08-30T20:31:31Z", "from" : { "type" : "user", "id" : "researchremix", "name" : "Heather Piwowar" } }, { "date" : "2010-08-30T20:08:13Z", "from" : { "type" : "user", "id" : "gregtyrelle", "private" : true, "name" : "Greg Tyrelle" } }, { "date" : "2010-08-30T19:21:13Z", "from" : { "type" : "user", "id" : "rvidal", "name" : "Ricardo Vidal" } }, { "date" : "2010-08-30T19:16:05Z", "from" : { "type" : "user", "id" : "yokofakun", "name" : "Pierre Lindenbaum" } }, { "date" : "2010-08-30T19:03:59Z", "from" : { "type" : "user", "id" : "egonw", "name" : "Egon Willighagen" } } ], "date" : "2010-08-30T18:57:48Z", "feed_id" : "oww", "feed_name" : "OpenWetWare", "feed_description" : "Share your science", "feed_type" : "group" },{ "_id" : "e/4ec53cbf129a488a9fc22672a2ccdbf1", "body" : "Welcome to my Lab Notebook Carl Boettiger - http://www.carlboettiger.info/archive...", "via" : { "url" : "http://friendfeed.com/share/bookmarklet", "name" : "Bookmarklet" }, "from" : { "type" : "user", "id" : "cboettig", "name" : "Carl Boettiger" }, "thumbnails" : [ { "url" : "http://m.friendfeed-media.com/f0fcbf940cd42b71e38a1c64b6ed30c30a76ee95", "width" : 300, "link" : "http://www.carlboettiger.info/archives/211", "height" : 123 } ], "url" : "http://friendfeed.com/science-2-0/4ec53cbf/welcome-to-my-lab-notebook-carl-boettiger", "comments" : [ { "date" : "2010-11-08T03:22:56Z", "body" : "I've written a post as an introduction to my open lab notebook, explaining how I view it and how it's organized and integrated with my github, flickr, and mendeley accounts. Still figuring things out, but think I've learned a lot about notebook workflow over the past 6 months. Feedback welcome!", "via" : { "url" : "http://friendfeed.com/share/bookmarklet", "name" : "Bookmarklet" }, "from" : { "type" : "user", "id" : "cboettig", "name" : "Carl Boettiger" }, "id" : "e/4ec53cbf129a488a9fc22672a2ccdbf1/c/cd641105864744519691f3371a29c4c2" }, { "date" : "2010-11-08T14:41:59Z", "body" : "Awesome explanation of what you are doing with ONS!", "from" : { "type" : "user", "id" : "jcbradley", "name" : "Jean-Claude Bradley" }, "id" : "e/4ec53cbf129a488a9fc22672a2ccdbf1/c/1dda34c17e9e47ccb077e0923eb232ed" } ], "to" : [ { "type" : "user", "id" : "cboettig", "name" : "Carl's feed" }, { "type" : "group", "id" : "science-2-0", "name" : "Science 2.0" }, { "type" : "group", "id" : "the-life-scientists", "name" : "The Life Scientists" }, { "type" : "group", "name" : "OpenWetWare", "id" : "oww" }, { "type" : "group", "id" : "scienceonline2012", "name" : "ScienceOnline2012" } ], "likes" : [ { "date" : "2010-12-06T00:21:26Z", "from" : { "type" : "user", "id" : "kubke", "name" : "Kubke" } }, { "date" : "2010-11-25T00:01:52Z", "from" : { "type" : "user", "id" : "pfanderson", "name" : "Patricia F. Anderson" } }, { "date" : "2010-11-18T09:10:27Z", "from" : { "type" : "user", "id" : "stevekoch", "name" : "Steve Koch" } }, { "date" : "2010-11-14T18:18:16Z", "from" : { "type" : "user", "id" : "byzia", "name" : "Piotr Byzia" } }, { "date" : "2010-11-12T10:21:50Z", "from" : { "type" : "user", "id" : "mrvaidya", "name" : "Gaurav Vaidya" } }, { "date" : "2010-11-11T23:17:36Z", "from" : { "type" : "user", "id" : "shwu", "name" : "Shirley Wu" } }, { "date" : "2010-11-09T07:02:48Z", "from" : { "type" : "user", "id" : "yarikson", "name" : "Yaroslav Nikolaev" } }, { "date" : "2010-11-08T21:19:04Z", "from" : { "type" : "user", "id" : "researchremix", "name" : "Heather Piwowar" } }, { "date" : "2010-11-08T20:11:58Z", "from" : { "type" : "user", "id" : "msscha", "name" : "Mickey Schafer" } }, { "date" : "2010-11-08T18:10:33Z", "from" : { "type" : "user", "id" : "hirosheridan", "name" : "Andrew Lang" } }, { "date" : "2010-11-08T15:21:27Z", "from" : { "type" : "user", "id" : "bersenev", "name" : "Alexey" } }, { "date" : "2010-11-08T15:01:59Z", "from" : { "type" : "user", "id" : "billhooker", "name" : "Bill Hooker" } }, { "date" : "2010-11-08T14:56:21Z", "from" : { "type" : "user", "id" : "sjcockell", "name" : "Simon Cockell" } }, { "date" : "2010-11-08T14:50:05Z", "from" : { "type" : "user", "id" : "lenhat", "private" : true, "name" : "len hat" } }, { "date" : "2010-11-08T14:48:58Z", "from" : { "type" : "user", "id" : "mndoci", "name" : "Deepak Singh" } }, { "date" : "2010-11-08T14:44:00Z", "from" : { "type" : "user", "id" : "kendrak", "private" : true, "name" : "kendrak" } }, { "date" : "2010-11-08T14:40:30Z", "from" : { "type" : "user", "id" : "jcbradley", "name" : "Jean-Claude Bradley" } }, { "date" : "2010-11-08T14:14:21Z", "from" : { "type" : "user", "id" : "gregdurablement", "name" : "GreG Durablement" } }, { "date" : "2010-11-08T13:28:32Z", "from" : { "type" : "user", "id" : "freesci", "name" : "Pawel Szczesny" } }, { "date" : "2010-11-08T10:07:58Z", "from" : { "type" : "user", "id" : "danielmietchen", "name" : "Daniel Mietchen" } }, { "date" : "2010-11-08T09:22:53Z", "from" : { "type" : "user", "id" : "cameronneylon", "name" : "Cameron Neylon" } }, { "date" : "2010-11-08T03:58:10Z", "from" : { "type" : "user", "id" : "suelibrarian", "private" : true, "name" : "suelibrarian" } }, { "date" : "2010-11-08T03:36:06Z", "from" : { "type" : "user", "id" : "mrgunn", "name" : "Mr. Gunn" } } ], "date" : "2010-11-08T03:22:56Z", "feed_id" : "oww", "feed_name" : "OpenWetWare", "feed_description" : "Share your science", "feed_type" : "group" },{ "_id" : "e/3810852d2879418eb300a6765cd9da23", "body" : "Seems OpenWetWare is down again. One reason I started hosting my notebook myself, but all of last year's entries still on OWW and it remains very useful! hope it's back up soon(?)", "from" : { "type" : "user", "id" : "cboettig", "name" : "Carl Boettiger" }, "url" : "http://friendfeed.com/oww/3810852d/seems-openwetware-is-down-again-one-reason-i", "to" : [ { "type" : "group", "name" : "OpenWetWare", "id" : "oww" } ], "date" : "2010-12-24T10:49:19Z", "feed_id" : "oww", "feed_name" : "OpenWetWare", "feed_description" : "Share your science", "feed_type" : "group" },{ "_id" : "e/0a3fdf4c87fa488f85717c16a581f7f8", "body" : "Fwd: Yep, open science works! My open dissertation outlines how to make a gliding motility assay using kinesin and microtubules. It took me nearly a year to perfect the procedure. It took a fellow graduate student at UCSC only two weeks to reproduce my procedures from my open dissertation and get the assay to work. Which, is not trivial and not...", "from" : { "type" : "user", "id" : "pfanderson", "name" : "Patricia F. Anderson" }, "url" : "http://friendfeed.com/opensci-info/0a3fdf4c/fwd-yep-open-science-works-my-dissertation", "to" : [ { "type" : "user", "id" : "pfanderson", "name" : "Patricia's feed" }, { "type" : "group", "id" : "opensci-info", "name" : "Open Science Info" }, { "type" : "group", "name" : "OpenWetWare", "id" : "oww" } ], "likes" : [ { "date" : "2011-02-28T21:13:43Z", "from" : { "type" : "user", "id" : "waterbetta", "private" : true, "name" : "Elisabetta Lambertini" } }, { "date" : "2011-02-28T14:01:54Z", "from" : { "type" : "user", "id" : "serifsiz", "private" : true, "name" : "feraye" } } ], "date" : "2011-02-28T14:01:19Z", "feed_id" : "oww", "feed_name" : "OpenWetWare", "feed_description" : "Share your science", "feed_type" : "group" }] 2 | --------------------------------------------------------------------------------