2013-03-19 4 views
5

私はNewtonsoft.Jsonを使用して、私のWebサービスからの出力をオブジェクトに逆シリアル化しています。 アバターを保持するためにUserという名前のクラスにBitmapプロパティを追加するまでうまくいきました。Newtonsoft.Jsonデシリアライズベース64イメージが失敗します

webserviceは、そのプロパティを期待どおりのBase64文字列として返しています。私はList<User>にWSからJSONをバック変換しようとすると問題がある 、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! 
    }); 

出力は次のとおりです。

Error converting value "System.Drawing.Bitmap" to type 'System.Drawing.Bitmap'. Path '[2].Avatar 

と見ています

{"Could not cast or convert from System.String to System.Drawing.Bitmap."} 

これは、Base64文字列を解析できないことは明らかですが、その理由は明らかではありません。

どのようなアイデアや回避策ですか?

EDIT は、私はバイト配列を取得し、そこからビットマップをロードしないConvert.FromBase64Stringを使用することができます知っています。その後、について質問するために私の質問を更新したいと思います。どのようにをスキップするか、または手動で解析することができますそのフィールド。 私は、すべてのJSONを手作業で解析することを避けたいと思います。 これも可能ですか?

EDITは2 私は、根本的な問題を見つけた:JSONが正しくWebサービスで連載されていない(と私は理由を見ることができません)。私はthisがやや異なる問題だと思ったが、それはなかった。私のWebサービスは、base64コンテンツの代わりに文字列"System.Drawing.Bitmap"を返すだけです。したがって、JsonSerializationException

私はこの問題を解決できませんでした。唯一の解決策は、自分のフィールドをbyte []にすることです。

答えて

9

あなたがして、画像のシリアライズ/デシリアライゼーションのを行うことができますBitmap.FromStream(new MemoryStream(bytearray));

EDIT

を使用して画像を取得し、文字列としてそのフィールドを読むConvert.FromBase64Stringを使用してアレイをバイトを

変換と

カスタムの助けコンバータ

public class AClass 
{ 
    public Bitmap image; 
    public int i; 
} 

Bitmap bmp = (Bitmap)Bitmap.FromFile(@"......"); 
var json = JsonConvert.SerializeObject(new AClass() { image = bmp, i = 666 }, 
             new ImageConverter()); 

var aclass = JsonConvert.DeserializeObject<AClass>(json, new ImageConverter()); 

これは私がSystem.Drawing.BitmapからBase64から逆シリアル化がサポートされていないことを考えるImageConverter

public class ImageConverter : Newtonsoft.Json.JsonConverter 
{ 
    public override bool CanConvert(Type objectType) 
    { 
     return objectType == typeof(Bitmap); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     var m = new MemoryStream(Convert.FromBase64String((string)reader.Value)); 
     return (Bitmap)Bitmap.FromStream(m); 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     Bitmap bmp = (Bitmap)value; 
     MemoryStream m = new MemoryStream(); 
     bmp.Save(m, System.Drawing.Imaging.ImageFormat.Jpeg); 

     writer.WriteValue(Convert.ToBase64String(m.ToArray())); 
    } 
} 
+0

を使用。 'JsonConvert.DeserializeObject (json)'にフィールドのみをスキップさせる方法がありますか?これはジェネリックメソッドの中にあるので、私は完全な手動解析を避けたいと思います... – Joel

+0

@Joel私の編集を参照してください.....正規表現やjson文字列を手動で解析する必要はありません。 – I4V

+0

このコードでは、手動でwebserviceでオブジェクトをシリアル化する必要がありますか? – Joel

1

です。 JSON.Net Ignore Property during deserialization

私はあなたが行うことができます最善を考える:かもしれあなたはすべてがここにEDITED QUESTION

FOR Avatarプロパティ

EDITはそれを行う方法についての興味深い議論ですexceptsでデシリアライズしてみてください

var newJsonString = Regex.Replace(jsonString, 
            "(\\,)* \"Avatar\": \"[A-Za-z0-9]+\"", 
            String.Empty); 

をして、目をデシリアライズ:JSON文字列からプロパティを削除するRegexを使用していますAvatarプロパティなしでnewJsonStringです。

後で、base64を取得し、あなたが正規表現や方法を改善することができ、それが基本的な考え方だBitmap

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; 
} 

を構築するために、元のJSON文字列を解析することができます。

+0

"アバタープロパティ以外のすべてをデシリアライズできます..." 手動ですべての要素を解析する必要はありませんか? – Joel

+1

a)Base64エンコーディングには64文字が必要ですが、この正規表現 'A-Za-z0-9'では62文字しか表示されません。b)正規表現でjsonを解析しようとするとうまくいきません。 c) "* Base64からSystem.Drawing.BitmapへのDeserializingはサポートされていないと思います。*"は正しくありません。 d) 'avatar'フィールドを文字列として宣言し、正規表現なしでC#でイメージを構築することができます。 –

6

これが私の解決策ですが、私は私の編集した質問を参照してください注釈

[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 
関連する問題