Объекты не сериализуются в XML (UTF-8), как ожидается .net? - PullRequest
0 голосов
/ 09 августа 2011

У меня есть вспомогательный метод, который сериализует объект, который работает до тех пор, пока вы не попытаетесь изменить кодировку ... при получении веб-службой потребителя кажется неправильным с некоторыми странными символами.

Здесьзаписи журнала из приложения,

UTF-16 (это работает):

2011-08-09 11:16:03,140 DEBUG SomeRestfulService *   xmlData    <?xml version="1.0" encoding="utf-8"?>
<loginRequest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <UserName>Admin</UserName>
  <Password>Password</Password>
  <MarketCode>GB</MarketCode>
</loginRequest>

UTF-8 (обратите внимание на странный символ):

2011-08-09 11:21:30,687 DEBUG SomeRestfulService *   xmlData    <?xml version="1.0" encoding="utf-8"?><loginRequest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><UserName>Admin</UserName><Password>Password</Password><MarketCode>GB</MarketCode></loginRequest>

Iне знаю, почему он потерял макет.

Вспомогательный метод:

Public Shared Function SerializeObject(ByVal obj As Object, ByVal encoding As Text.Encoding) As String

    Dim serializer As New XmlSerializer(obj.GetType)

    If encoding Is Nothing Then
        Using strWriter As New IO.StringWriter()
            serializer.Serialize(strWriter, obj)
            Return strWriter.ToString
        End Using
    Else
        Using stream As New IO.MemoryStream, xtWriter As New Xml.XmlTextWriter(stream, encoding)
            serializer.Serialize(xtWriter, obj)
            Return encoding.GetString(stream.ToArray())
        End Using
    End If


End Function

Примечание: если я передаю кодирование как ничего, кодировка по умолчанию - UTF-16, все в порядкеИзначально у меня никогда не было части кодирования, но это требование, поэтому оно должно быть там.

Я неправильно выполняю сериализацию при кодировании в UTF-8?Как я могу это исправить?

Я попробовал следующее, чтобы опустить спецификацию, но все еще проблема та же:

Dim utf8 As New Text.UTF8Encoding(True)
Using stream As New IO.MemoryStream, xtWriter As New Xml.XmlTextWriter(stream, utf8)
    serializer.Serialize(xtWriter, obj)
    Return utf8.GetString(stream.ToArray())
End Using

1 Ответ

1 голос
/ 09 августа 2011

Вы видите метку порядка байтов (BOM), которая часто используется в начале текстовых файлов или потоков для указания порядка байтов и варианта Unicode.

Ваш сериализатор очень странный.Если вы кодируете строку с некоторой кодировкой, такой как UTF-8, вы должны вернуть ее в виде массива байтов.Сначала кодируя XML-код в UTF-8, а затем декодируя поток UTF-8 обратно в строку, вы ничего не получите (кроме введения проблемной спецификации).

Либо используйте только UTF-16, либо вернитебайтовый массив.Теперь, когда эта функция работает, кодирование просто создает проблемы.

Обновление:

На основе кода, приведенного в комментарии ниже, я увижу два подхода:

Подход 1: Создать строку с сериализованными данными и преобразовать ее в UTF-8 позднее

Public Shared Function SerializeObject(ByVal obj As Object) As String

    Dim serializer As New XmlSerializer(obj.GetType)

    Using strWriter As New IO.StringWriter()
        serializer.Serialize(strWriter, obj)
        Return strWriter.ToString
    End Using

End Function

....

Dim serialisedObject As String = SerializeObject(object)
Dim postData As Byte() = New Text.UTF8Encoding(True).GetBytes(serialisedObject)

Если вам нужна другая кодировка, измените последнюю строку.Если вы хотите опустить метку порядка байтов, передайте False в UTF8Encoding().

Подход 2. Сначала создайте правильно закодированные данные и продолжайте с байтовым массивом

Public Shared Function SerializeObject(ByVal obj As Object, ByVal encoding As Text.Encoding) As Byte()

    Dim serializer As New XmlSerializer(obj.GetType)

    If encoding Is Nothing Then
       Set encoding = Encoding.Unicode
    End If

    Using stream As New IO.MemoryStream, xtWriter As New Xml.XmlTextWriter(stream, encoding)
        serializer.Serialize(xtWriter, obj)
        Return stream.ToArray()
    End Using

End Function


....

Dim postData As Byte() = SerializeObject(object)

В этом случае XmlTextWriter непосредственно кодирует данные с правильной кодировкой.Поскольку у нас уже есть байтовый массив, последний шаг короче: у нас есть данные для отправки клиенту.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...