相当于Perl 5 utf :: decode

时间:2018-02-06 13:43:12

标签: json go unicode utf-8

在Go?

中,这个Perl程序的等价物是什么?
use utf8;
my $bin = "..."; # the data may came from file, network, etc
utf8::decode( $bin ); # Encode::decode( 'UTF-8', $bin ) also works

http://perldoc.perl.org/utf8.html

中定义

我尝试了几种形式的转换/规范化/转换为bytes / runes / etc而没有成功。

上下文:

我使用Sereal(https://github.com/Sereal/Sereal)来序列化NoSQL数据库中的一些数据结构,首先我们有一个Perl 5.12.2版本,我们正在使用Go。 Sereal格式是二进制文件

然而,不知何故,一些perl程序在最终的BLOB(UTF-8字符串)中进行了额外的JSON编码/解码,因此对于perl程序读取和写入数据来说很好,但是当Go尝试解码它时不行。

当然,最好的解决方案是停止这种双重编码,但由于我们的数据库中有这种格式的条目,我想看看我是否可以尝试解码它

概念验证 - 这是我的Json,带有来自我的sereal字节的utf-8转换字符串

$ hexdump -C min.bin 
00000000  22 3d c3 b3 72 6c 5c 75  30 30 30 33 5c 75 30 30  |"=..rl\u0003\u00|
00000010  30 30 51 6b 6c 61 73 74  5f 75 70 64 61 74 65 20  |00Qklast_update |
00000020  c2 82 c3 9a c3 a6 c3 93  5c 75 30 30 30 35 22     |........\u0005"|
0000002f

decode.pl

use strict;
use warnings;
use JSON;
use Sereal::Decoder;
use Data::Dumper;
use File::Slurp;

my $data = read_file( "min.bin", { binmode => ':raw' } );
my $bin = JSON->new->allow_nonref(1)->decode( $data );
utf8::decode( $bin ); # MAGIC !!!
my $out = Sereal::Decoder->new->decode( $bin );
print(Dumper( $out ));

输出

$VAR1 = {
          'last_update' => 1517923586
        };

decode.go

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"

    "github.com/Sereal/Sereal/Go/sereal"
    "github.com/davecgh/go-spew/spew"
)

func main() {
    data, err := ioutil.ReadFile("min.bin")
    if err != nil {
        fmt.Printf("unexpected error while reading fixtures file: '%+v'\n", err)
    }
    var v interface{}
    err = json.Unmarshal(data, &v)
    spew.Dump(v, err)

    var vbody interface{}
    instance := sereal.NewDecoder()
    instance.PerlCompat = false
    str := v.(string)
    // something here to be able to decode?
    err = instance.Unmarshal([]byte(str), vbody)
    spew.Dump(vbody, err)
}

输出

(string) (len=30) "=órl\x03\x00Qklast_update \u0082ÚæÓ\x05"
(interface {}) <nil>
(interface {}) <nil>
(*errors.errorString)(0xc42000e370)(bad header: it seems your document was accidentally UTF-8 encoded)

编辑:此代码有效,但我认为这不是正确的方法:

  buff := &bytes.Buffer{}
  for len(s) > 0 {
     r, size := utf8.DecodeRuneInString( s )
     buff.WriteByte( byte(r ) ) 
     s = s[size:]
  }

  rawBytes := buff.Bytes() // yeah

此致

蒂亚戈

0 个答案:

没有答案