Проблема при сериализации объектов со строками, которые содержат "/" - PullRequest
0 голосов
/ 25 октября 2018

Я использую DataContractJsonSerializer для сериализации объекта, и для этого я использую следующую функцию:

public static string Serialize<T>(T obj)
{
    string returnVal = "";
    try
    {
        DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType());
        using (MemoryStream ms = new MemoryStream())
        {
            serializer.WriteObject(ms, obj);
            returnVal = Encoding.UTF8.GetString(ms.ToArray());
        }
    }
    catch (Exception /*exception*/)
    {
        returnVal = "";
         //log error
    }
    return returnVal;
}

Теперь эта функция работает хорошо и отлично .... за исключением следующей ситуации (я сомневаюсь, если это изменить, поскольку я не знаю, как это повлияет на остальную часть моего кода).

Ситуация, в которой он не работаетну

скажем, у меня есть obj (аргумент) объект, такой как:

[DataContract()]
public class theObject
{
   [DataMember()]
   public string image;
}

, в котором image содержит значение Base64 BMPфайл.Это большое значение, но, например, оно должно начинаться с: "Qk1W/QAAAAAAADYAAAAoAAAAawAAAMgAAAABABgAAAAAACD9AADEDgAAxA4AAAAAAAAAAAAA////////////////////////////////////7+/...."

Итак, вы видите, что оно содержит много / с.

Так что, когда я передаю этот объект в Serialize, он будет WriteObject в мс, а затем получит это в массив, который в конечном итоге перейдет к returnVal.

Теперь давайте рассмотрим returnVal.Он в формате JSON (правильный), и когда вы представите его как JSON, он покажет вам:

image:"Qk1W/QAAAAAAADYAAAAoAAAAawAAAMgAAAABABgAAAAAACD9AADEDgAAxA4AAAAAAAAAAAAA////////////////////////////////////7+/...."

Однако!когда вы визуализируете его как текст, он покажет вам:

"image":"Qk1W\/QAAAAAAADYAAAAoAAAAawAAAMgAAAABABgAAAAAACD9AADEDgAAxA4AAAAAAAAAAAAA\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/7+\/..."

Вы видели?он вставляет \ перед каждым /, и это имеет большое значение.

Итак, мои вопросы:

  1. Зачем визуализировать его как JSON, а визуализировать как текст показывает разные вещи?
  2. Как я могу получить после сериализации правильное значение (без / с)

РЕДАКТИРОВАТЬ:

Хотя можно сказать, что \/ и / одинаковы, последствия не являются.Позже при использовании этого JSON для выброса его в Web Api с использованием

byte[] bytes = Encoding.UTF8.GetBytes(json);

ByteArrayContent byteContent = new ByteArrayContent(bytes);                    
byteContent.Headers.ContentType = new MediaTypeWithQualityHeaderValue(content);

версия с добавленным \ приводит к bytes с 115442 байтами, в то время как версия, которая использует только /, приводит к bytes из 86535 байт.Поэтому результаты совершенно разные.

Итак, как я могу получить результат без добавления \ с?

1 Ответ

0 голосов
/ 16 ноября 2018

Стандартным поведением DataContractJsonSerializer является экранирование / символов в строках, чтобы они стали \/ в JSON.Когда JSON десериализуется обратно в объект, escape-последовательности \/ будут возвращены в /, поэтому данные не будут потеряны или повреждены.(Попробуйте и посмотрите.) Однако это приводит к увеличению размера JSON в байтах.Если это действительно вас беспокоит, есть несколько вещей, которые вы можете сделать, чтобы обойти это:

Подход 1

Сразу после сериализации вы можете использовать string.Replace() чтобы избавиться от всех обратных косых черт, которые появляются непосредственно перед косыми чертами.Вы можете сделать это прямо в вашем методе Serialize, изменив эту строку:

returnVal = Encoding.UTF8.GetString(ms.ToArray());

на:

returnVal = Encoding.UTF8.GetString(ms.ToArray()).Replace("\\/", "/");

Поскольку / не имеет специального значения в JSON, это нена самом деле необходимо избегать их с \, хотя это допустимо.(См. Стр. 5 спецификации JSON .) DataContractJsonSerializer все равно будет десериализовать JSON очень хорошо, даже если косые черты не экранированы.(Попробуйте сами и посмотрите. Я бы сделал для этого скрипку, но .NET Fiddle не поддерживает DataContractJsonSerializer).

Подход 2 (рекомендуется)

Переключиться на лучший сериализатор JSON, такой как Json.Net , который не избежит косой черты в первую очередь,Вы можете упростить свой код и заменить весь метод Serialize на JsonConvert.SerializeObject()

Fiddle: https://dotnetfiddle.net/MQKXSD

...