diff --git a/pkg/goutils/goutils.go b/pkg/goutils/goutils.go index 8bd0308..f4eeaab 100644 --- a/pkg/goutils/goutils.go +++ b/pkg/goutils/goutils.go @@ -4,6 +4,7 @@ import ( "bufio" "bytes" "encoding/gob" + "encoding/json" "io" "os" "sync" @@ -188,3 +189,17 @@ func AtomicCounter(initial ...int) func() int { return nextCounter } + +// Marshal is a UTF-8 friendly marshaler. Go's json.Marshal is not UTF-8 +// friendly because it replaces the valid UTF-8 and JSON characters "&". "<", +// ">" with the "slash u" unicode escaped forms (e.g. \u0026). It preemptively +// escapes for HTML friendliness. Where text may include any of these +// characters, json.Marshal should not be used. Playground of Go breaking a +// title: https://play.golang.org/p/o2hiX0c62oN +func JsonMarshal(i interface{}) ([]byte, error) { + buffer := &bytes.Buffer{} + encoder := json.NewEncoder(buffer) + encoder.SetEscapeHTML(false) + err := encoder.Encode(i) + return bytes.TrimRight(buffer.Bytes(), "\n"), err +} diff --git a/pkg/obiformats/fastseq_json_header.go b/pkg/obiformats/fastseq_json_header.go index a8cefbf..f4d6481 100644 --- a/pkg/obiformats/fastseq_json_header.go +++ b/pkg/obiformats/fastseq_json_header.go @@ -6,6 +6,7 @@ import ( log "github.com/sirupsen/logrus" + "git.metabarcoding.org/lecasofts/go/obitools/pkg/goutils" "git.metabarcoding.org/lecasofts/go/obitools/pkg/obiseq" "github.com/goccy/go-json" ) @@ -70,7 +71,7 @@ func FormatFastSeqJsonHeader(sequence *obiseq.BioSequence) string { annotations := sequence.Annotations() if annotations != nil { - text, err := json.Marshal(sequence.Annotations()) + text, err := goutils.JsonMarshal(sequence.Annotations()) if err != nil { panic(err) diff --git a/pkg/obiformats/fastseq_obi_header.go b/pkg/obiformats/fastseq_obi_header.go index 1710bbf..faa92ca 100644 --- a/pkg/obiformats/fastseq_obi_header.go +++ b/pkg/obiformats/fastseq_obi_header.go @@ -9,6 +9,7 @@ import ( "strconv" "strings" + "git.metabarcoding.org/lecasofts/go/obitools/pkg/goutils" "git.metabarcoding.org/lecasofts/go/obitools/pkg/obiseq" "github.com/goccy/go-json" ) @@ -216,16 +217,18 @@ func ParseOBIFeatures(text string, annotations obiseq.Annotation) string { dict := make(map[string]int) err = json.Unmarshal(j, &dict) value = dict - case strings.HasSuffix(key, "_status"): + case strings.HasSuffix(key, "_status") || + strings.HasSuffix(key, "_mutation"): dict := make(map[string]string) err = json.Unmarshal(j, &dict) value = dict + default: dict := make(map[string]interface{}) err = json.Unmarshal(j, &dict) value = dict } - + if err != nil { value = string(bvalue) } @@ -299,9 +302,10 @@ func FormatFastSeqOBIHeader(sequence *obiseq.BioSequence) string { case string: text.WriteString(fmt.Sprintf("%s=%s; ", key, t)) case map[string]int, + map[string]string, map[string]interface{}, obiseq.StatsOnValues: - tv, err := json.Marshal(t) + tv, err := goutils.JsonMarshal(t) if err != nil { log.Fatalf("Cannot convert %v value", value) }