2012-02-20 4 views
1

SOAP :: Liteを使用して複雑なデータ構造でUTF-8文字列を送信しようとしています。しかし、それが判明したので、SOAP::Lite quietly converts all UTF-8 strings into base-64-encoded octets。その問題は、逆シリアル化がdoes not revert the conversionで、a straight base64 decodeのみであることです。SOAP :: LiteがUTF-8として応答でUTF-8データを返すようにするにはどうすればよいですか?

これは、ユーザーがSOAP :: LiteレスポンスからUTF-8データを取得する方法を混乱させるものです。ツリーを歩いて、すべての文字列にdecode_utf8を実行すると無駄になります。

提案がありますか?

編集:簡単に言えば、this testを猿のパッチなしでパスするにはどうすればよいですか?

+0

あなたはXML :: Compileを考えましたか?これは複雑なコードですが、著者は正しいサポートのために細心の注意を払っています。私が知っている人から、それを使った人は、あなたがそれを見つけたら、この物の方がはるかに優れています。私はそれ自身で経験がありません。 –

+0

最後に私はそれを見て、私は最初にそれを使う方法を理解できませんでした。私は必要なドメイン知識がないと思う(XSDなどを書いて)。 – Mithaldu

答えて

0

is_utf8(278行目)の使用は邪悪で間違っています。文字データを適切にエンコードしてSOAP :: Liteを正しく信用できないので(公正であるように、このコードは、この特定の種類の文字列処理を行う方法をコミュニティ内で知った前に書かれた可能性が高い)、オクテットデータのみ自分自身をエンコード/デコードする必要があります。単一のエンコーディングを選択し、データをS :: Lに渡す前にそれを適用し、データを受け取った後にそれを取り消します。

use utf8; 
use strictures; 
use Encode qw(decode encode); 
use SOAP::Lite qw(); 
use Test::More; 

my $original = 'mü'; 
my $xml  = SOAP::Serializer->envelope(
    freeform => encode('UTF-8', $original, Encode::FB_CROAK | Encode::LEAVE_SRC) 
); 
my ($roundtrip) = map { 
    decode('UTF-8', $_, Encode::FB_CROAK | Encode::LEAVE_SRC) 
} values %{SOAP::Deserializer->deserialize($xml)->body}; 

is(length($original), length($roundtrip), 
    'Perl character string round-trips without changing length'); 
done_testing; 
+0

「複雑なデータ構造」とはどういうことに注意してください。理解の努力を低く抑えるためにテストは最小ですが、20kバイト程度までダンプする4次元ハッシュだと想像してください。 :) – Mithaldu

+1

その後、UTF-8ではなくJSONにエンコードします。 – daxim

+0

私はそれを浮かべることができます。私はSOAPサーバーを完全に制御することはできませんが、彼は提案にはオープンになると思います。アイデアをありがとう。 – Mithaldu

1

私はちょうど同じ問題にぶつかり、上記の議論が役に立ちました。 OPで言うように、問題は、データがbase64でエンコードされ、is_utf8フラグが失われるということです。 serlializerで何が起こるかは、非ASCII文字を持つ文字列をバイナリとして扱います。私は以下のようにシリアライザを調整することで、私が望むことをすることができました。 9がUTF8のチェックが非ASCII文字のチェックの前に実行されることを意味

use strictures; 
use Test::More; 
use SOAP::Lite; 
use utf8; 
use Data::Dumper; 

my $data = "mü\x{2013}"; 
my $ser = SOAP::Serializer->new; 
$ser->typelookup->{trick_into_ignoring} = [9, \&utf8::is_utf8 ,'as_utf8_string']; 
my $xml = $ser->envelope(freeform => $data); 
my ($cycled) = values %{ SOAP::Deserializer->deserialize($xml)->body }; 

is(length($data), length($cycled), "UTF-8 string is the same after serializing"); 
done_testing; 

sub check_utf8 { 
    my ($val) = @_; 
    return utf8::is_utf8($val); 
} 


package SOAP::Serializer; 
sub as_utf8_string { 
    my $self = shift; 
    my($value, $name, $type, $attr) = @_; 
    return $self->as_string($value, $name, $type, $attr); 
} 
1; 

...それは奇妙な結果をもたらす可能性が、それは私の状況で動作します。 utf8フラグがオンの場合、それは '通常の'文字列として扱われます。

関連する問題