Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Json反序列化base64映像失败_C#_.net_Json_Image - Fatal编程技术网

C# Json反序列化base64映像失败

C# Json反序列化base64映像失败,c#,.net,json,image,C#,.net,Json,Image,我正在使用Newtonsoft.Json将Web服务的输出反序列化为对象。 在我将位图属性添加到我的类(名为用户)中以保存化身之前,它工作得很好 webservice正在以Base64字符串的形式返回该属性,这与预期的一样。 问题是,当我尝试将JSON从WS转换回列表时,会在这段代码中抛出JsonSerializationException: // T is IList<User> response.Content.ReadAsStringAsync().Proceed( (

我正在使用Newtonsoft.Json将Web服务的输出反序列化为对象。 在我将
位图
属性添加到我的类(名为
用户
)中以保存化身之前,它工作得很好

webservice正在以Base64字符串的形式返回该属性,这与预期的一样。 问题是,当我尝试将JSON从WS转换回
列表时,会在这段代码中抛出
JsonSerializationException

// T is IList<User>
response.Content.ReadAsStringAsync().Proceed(
    (readTask) =>
    {
        var json = ((Task<string>)readTask).Result;
        var result = JsonConvert.DeserializeObject<T>(json); //<-- it fails here

         // do stuff! 
     });
看看内部异常:

{"Could not cast or convert from System.String to System.Drawing.Bitmap."}
很明显,它无法解析Base64字符串,但不清楚原因

有什么想法/解决方法吗

编辑 我知道我可以使用
Convert.FromBase64String
获取字节数组并从中加载位图。然后我想更新我的问题,询问如何跳过或手动解析该字段。 我希望避免手动解析所有JSON。 这可能吗

编辑2 我发现了根本问题:JSON在webservice中没有被正确序列化(我不明白为什么)。我认为这是一个有点不同的问题,但不是。我的Web服务只是返回一个字符串
“System.Drawing.Bitmap”
,而不是它的base64内容。因此出现了
JsonSerializationException


我一直无法解决这个问题,我找到的唯一解决办法是将我的字段转换为
字节[]

将该字段读取为字符串

使用
convert.FromBase64String

使用
Bitmap.FromStream(newmemorystream(bytearray))获取图像

编辑

您可以在自定义转换器的帮助下执行图像序列化/反序列化


我认为不支持从
Base64
反序列化到
System.Drawing.Bitmap
。可能您可以尝试反序列化除
Avatar
属性之外的所有内容

编辑已编辑的问题

下面是一个关于如何做到这一点的有趣讨论:

我认为您最好使用
Regex
从json字符串中删除属性:

var newJsonString = Regex.Replace(jsonString, 
                                  "(\\,)* \"Avatar\": \"[A-Za-z0-9]+\"", 
                                  String.Empty);
然后反序列化这个
newJsonString
,而不使用Avatar属性

稍后,您可以解析原始json字符串以获取
base64
,并构建
位图

var avatarBase64 = Regex.Match(
                        Regex.Match(json, "(\\,)* \"Avatar\": \"[A-Za-z0-9]+\"")
                             .ToString(), 
                        "[A-Za-z0-9]+", RegexOptions.RightToLeft)
                        .ToString();

...

byte[] fromBase64 = Convert.FromBase64String(avatarBase64);
using (MemoryStream ms = new MemoryStream(fromBase64))
{
    Bitmap img = (Bitmap)Image.FromStream(ms);
    result.Avatar = img;
}

您可以改进正则表达式或方法,但这是基本思想。

这是我的解决方案,我使用了注释

[Serializable]
public class MyClass
{
    [JsonConverter(typeof(CustomBitmapConverter))]
    public Bitmap MyImage { get; set; }


    #region JsonConverterBitmap
    internal class CustomBitmapConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return true;
        }

        //convert from byte to bitmap (deserialize)

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            string image = (string)reader.Value;

            byte[] byteBuffer = Convert.FromBase64String(image);
            MemoryStream memoryStream = new MemoryStream(byteBuffer);
            memoryStream.Position = 0;

            return (Bitmap)Bitmap.FromStream(memoryStream);
        }

        //convert bitmap to byte (serialize)
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            Bitmap bitmap = (Bitmap)value;

            ImageConverter converter = new ImageConverter();
            writer.WriteValue((byte[])converter.ConvertTo(bitmap, typeof(byte[])));
        }

        public static System.Drawing.Imaging.ImageFormat GetImageFormat(Bitmap bitmap)
        {
            ImageFormat img = bitmap.RawFormat;

            if (img.Equals(System.Drawing.Imaging.ImageFormat.Jpeg))
                return System.Drawing.Imaging.ImageFormat.Jpeg;
            if (img.Equals(System.Drawing.Imaging.ImageFormat.Bmp))
                return System.Drawing.Imaging.ImageFormat.Bmp;
            if (img.Equals(System.Drawing.Imaging.ImageFormat.Png))
                return System.Drawing.Imaging.ImageFormat.Png;
            if (img.Equals(System.Drawing.Imaging.ImageFormat.Emf))
                return System.Drawing.Imaging.ImageFormat.Emf;
            if (img.Equals(System.Drawing.Imaging.ImageFormat.Exif))
                return System.Drawing.Imaging.ImageFormat.Exif;
            if (img.Equals(System.Drawing.Imaging.ImageFormat.Gif))
                return System.Drawing.Imaging.ImageFormat.Gif;
            if (img.Equals(System.Drawing.Imaging.ImageFormat.Icon))
                return System.Drawing.Imaging.ImageFormat.Icon;
            if (img.Equals(System.Drawing.Imaging.ImageFormat.MemoryBmp))
                return System.Drawing.Imaging.ImageFormat.MemoryBmp;
            if (img.Equals(System.Drawing.Imaging.ImageFormat.Tiff))
                return System.Drawing.Imaging.ImageFormat.Tiff;
            else
                return System.Drawing.Imaging.ImageFormat.Wmf;
        }

    }

    #endregion

请参考我编辑的问题。有没有办法让
JsonConvert.DeserializeObject(json)
只跳过一个字段?这是在一个通用方法中,因此我希望避免完全手动解析…使用此代码,我必须手动序列化Web服务中的对象,对吗?@Joel no。如果字段/属性的类型为
Bitmap
,则此代码将base64编码字符串反序列化为位图。请参阅
AClass的定义
请参阅我的更新。你的解决方案很有希望,但我无法测试它,因为根本问题已经改变了。如果我解决了这个问题,我一定会测试你的解决方案。@Joel只需使用
JsonConvert.SerializeObject(你的对象,new ImageConverter())“您可以尝试反序列化除Avatar属性之外的所有内容…”有没有一种方法可以做到这一点而不必手动解析所有元素?a)Base64编码需要64个字符,但我在这个正则表达式中只看到62个
a-Za-z0-9
b)尝试用正则表达式解析json并不好。c) “我认为不支持从Base64反序列化到System.Drawing.Bitmap。”不正确。d) 您可以将
avatar
字段声明为字符串,并在不使用正则表达式的情况下用c#构建图像。
var newJsonString = Regex.Replace(jsonString, 
                                  "(\\,)* \"Avatar\": \"[A-Za-z0-9]+\"", 
                                  String.Empty);
var avatarBase64 = Regex.Match(
                        Regex.Match(json, "(\\,)* \"Avatar\": \"[A-Za-z0-9]+\"")
                             .ToString(), 
                        "[A-Za-z0-9]+", RegexOptions.RightToLeft)
                        .ToString();

...

byte[] fromBase64 = Convert.FromBase64String(avatarBase64);
using (MemoryStream ms = new MemoryStream(fromBase64))
{
    Bitmap img = (Bitmap)Image.FromStream(ms);
    result.Avatar = img;
}
[Serializable]
public class MyClass
{
    [JsonConverter(typeof(CustomBitmapConverter))]
    public Bitmap MyImage { get; set; }


    #region JsonConverterBitmap
    internal class CustomBitmapConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return true;
        }

        //convert from byte to bitmap (deserialize)

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            string image = (string)reader.Value;

            byte[] byteBuffer = Convert.FromBase64String(image);
            MemoryStream memoryStream = new MemoryStream(byteBuffer);
            memoryStream.Position = 0;

            return (Bitmap)Bitmap.FromStream(memoryStream);
        }

        //convert bitmap to byte (serialize)
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            Bitmap bitmap = (Bitmap)value;

            ImageConverter converter = new ImageConverter();
            writer.WriteValue((byte[])converter.ConvertTo(bitmap, typeof(byte[])));
        }

        public static System.Drawing.Imaging.ImageFormat GetImageFormat(Bitmap bitmap)
        {
            ImageFormat img = bitmap.RawFormat;

            if (img.Equals(System.Drawing.Imaging.ImageFormat.Jpeg))
                return System.Drawing.Imaging.ImageFormat.Jpeg;
            if (img.Equals(System.Drawing.Imaging.ImageFormat.Bmp))
                return System.Drawing.Imaging.ImageFormat.Bmp;
            if (img.Equals(System.Drawing.Imaging.ImageFormat.Png))
                return System.Drawing.Imaging.ImageFormat.Png;
            if (img.Equals(System.Drawing.Imaging.ImageFormat.Emf))
                return System.Drawing.Imaging.ImageFormat.Emf;
            if (img.Equals(System.Drawing.Imaging.ImageFormat.Exif))
                return System.Drawing.Imaging.ImageFormat.Exif;
            if (img.Equals(System.Drawing.Imaging.ImageFormat.Gif))
                return System.Drawing.Imaging.ImageFormat.Gif;
            if (img.Equals(System.Drawing.Imaging.ImageFormat.Icon))
                return System.Drawing.Imaging.ImageFormat.Icon;
            if (img.Equals(System.Drawing.Imaging.ImageFormat.MemoryBmp))
                return System.Drawing.Imaging.ImageFormat.MemoryBmp;
            if (img.Equals(System.Drawing.Imaging.ImageFormat.Tiff))
                return System.Drawing.Imaging.ImageFormat.Tiff;
            else
                return System.Drawing.Imaging.ImageFormat.Wmf;
        }

    }

    #endregion