title: Deserialize JSON with embedded Dictionary<string, string>
body: <p>I need to determine if the DataContractJsonSerializer can deserialize JSON to a Dictionary if the Dictionary is not the wrapping object being deserialized. I know there are other open source codes projects that may be able to do this (json.net, json-framework) but I'd like to know definitively if .NET can natively handle this before taking that approach. all the <a href="http://msdn.microsoft.com/en-us/library/aa347850.aspx" rel="nofollow noreferrer">MSDN documentation</a> suggests it can but I am not sure if I am handling the conversion correctly.  </p>
  
  <p>So to start I'm receiving a video object from a web service in JSON like this:</p>
  
  <pre><code>{"videos":
   [{
    "id":000000000000,
    "name":"Video Title",
    "adKeys":null,
    "shortDescription":"short description",
    "longDescription":"long description",
    "creationDate":"1282819270274",
    "publishedDate":"1282819270274",
    "lastModifiedDate":"1282857505013",
    "linkURL":null,
    "linkText":null,
    "tags":["tag1","tag2","tag3","tag4","tag5","tag5"],
    "videoStillURL":"",
    "thumbnailURL":"",
    "referenceId":"0000",
    "length":177679,
    "economics":"AD_SUPPORTED",
    "playsTotal":178,
    "playsTrailingWeek":178,
    "customFields":{"custom title":"custom value", "custom title 2":"custom value2"},
    "FLVURL":"",
    "renditions":[]
   }],
  "page_number":0,
  "page_size":0,
  "total_count":1}
  </code></pre>
  
  <p>I am deserializing this object as a BCQueryResult. The BCQueryResult has a property called Videos that is a BCCollection which extends List and applies a CollectionDataContract. The video object in turn has a property called customFields that is a CustomFields object which extends Dictionary and applies a CollectionDataContract. All collection types that are List types(videos, tags, cuepoints etc.) are deserialized without issue. The Dictionary type is the only type that has a problem deserializing. There is no error but even when a value is present the result is empty. If I strip out all date types and deserialize with the JavaScriptSerializer it will give me the proper value, but because of issues with required field types I cannot use the JavaScriptSerializer instead I am using the DataContractJsonSerializer. I've attached the classes below. </p>
  
  <p><strong>BCQueryResult:</strong></p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Runtime.Serialization;
  using BrightcoveSDK.Media;
  
  namespace BrightcoveSDK
  {
   [DataContract]
   public class BCQueryResult
   {
    [DataMember(Name = "videos")]
    public BCCollection&lt;BCVideo&gt; Videos;
    [DataMember(Name = "playlists")]
    public BCCollection&lt;BCPlaylist&gt; Playlists;
    [DataMember(Name = "page_number")]
    public int PageNumber { get; set; }
    [DataMember(Name = "page_size")]
    public int PageSize { get; set; }
    [DataMember(Name = "total_count")]
    public int TotalCount { get; set; }
  
    public int MaxToGet = 0;
    public List&lt;QueryResultPair&gt; QueryResults = new List&lt;QueryResultPair&gt;();
  
    public BCQueryResult() {
     Playlists = new BCCollection&lt;BCPlaylist&gt;();
     Videos = new BCCollection&lt;BCVideo&gt;();
     PageNumber = 0;
     PageSize = 0;
     TotalCount = 0;
    }
  
    public void Merge(BCQueryResult qr) {
  
     //if (qr.QueryResults != null &amp;&amp; qr.QueryResults.Count &gt; 0)
     //        QueryResults.Add(qr.QueryResults[qr.QueryResults.Count -1]);
     if (qr.Videos != null) Videos.AddRange(qr.Videos);
     if(qr.Playlists != null) Playlists.AddRange(qr.Playlists);
     PageNumber = qr.PageNumber;
     TotalCount = qr.TotalCount;
     PageSize = qr.PageSize;
    }
   }
  }
  </code></pre>
  
  <p>BCCollection:</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Runtime.Serialization;
  
  namespace BrightcoveSDK
  {
   [CollectionDataContract]
   public class BCCollection&lt;T&gt; : List&lt;T&gt;
   {}
  
   public static class BCCollectionExtensions {
  
    public static string ToDelimitedString(this BCCollection&lt;string&gt; list, string Delimiter) {
  
     string r = "";
     foreach (string s in list) {
      if (r.Length &gt; 0) {
       r += Delimiter;
      }
      r += s;
     }
     return r;
    }
   }
  }
  </code></pre>
  
  <p>BCVideo:</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Net;
  using System.Text;
  using System.Web;
  using System.Runtime.Serialization;
  
  namespace BrightcoveSDK.Media
  {
   /// &lt;summary&gt;
   /// The Video object is an aggregation of metadata and asset information associated with a video
   /// &lt;/summary&gt;
   [DataContract]
   public class BCVideo : BCObject, IComparable&lt;BCVideo&gt;
   {
    /// &lt;summary&gt;
    /// A number that uniquely identifies this Video, assigned by Brightcove when the Video is created.
    /// &lt;/summary&gt;
    [DataMember]
    public long id { get; set; }
  
    /// &lt;summary&gt;
    /// The title of this Video.
    /// &lt;/summary&gt; 
    [DataMember]
    public string name { get; set; }
  
    /// &lt;summary&gt;
    /// A short description describing this Video, limited to 256 characters.
    /// &lt;/summary&gt; 
    [DataMember]
    public string shortDescription { get; set; }
  
    /// &lt;summary&gt;
    /// A longer description of this Video, bounded by a 1024 character limit.
    /// &lt;/summary&gt; 
    [DataMember]
    public string longDescription { get; set; }
  
    [DataMember(Name = "creationDate")]
    private string createDate { get; set; }
  
    /// &lt;summary&gt;
    /// The date this Video was created, represented as the number of milliseconds since the Unix epoch.
    /// &lt;/summary&gt; 
    public DateTime creationDate {
     get {
      return DateFromUnix(createDate);
     }
     set {
      createDate = DateToUnix(value);
     }
    }
  
    [DataMember(Name = "publishedDate")]
    private string publishDate { get; set; }
  
    /// &lt;summary&gt;
    /// The date this Video was last made active, represented as the number of milliseconds since the Unix epoch.
    /// &lt;/summary&gt; 
    public DateTime publishedDate {
     get {
      return DateFromUnix(publishDate);
     }
     set {
      publishDate = DateToUnix(value);
     }
    }
  
    [DataMember(Name = "lastModifiedDate")]
    private string modifyDate { get; set; }
  
    /// &lt;summary&gt;
    /// The date this Video was last modified, represented as the number of milliseconds since the Unix epoch.
    /// &lt;/summary&gt; 
    public DateTime lastModifiedDate {
     get {
      return DateFromUnix(modifyDate);
     }
     set {
      modifyDate = DateToUnix(value);
     }
    }
  
    /// &lt;summary&gt;
    /// An optional URL to a related item.
    /// &lt;/summary&gt; 
    [DataMember]
    public string linkURL { get; set; }
  
    /// &lt;summary&gt;
    /// The text displayed for the linkURL.
    /// &lt;/summary&gt; 
    [DataMember]
    public string linkText { get; set; }
  
    [DataMember(Name = "FLVURL")]
    public string flvURL { get; set; }
  
          private BCCollection&lt;string&gt; _tags;
  
    /// &lt;summary&gt;
    /// A list of Strings representing the tags assigned to this Video.
    /// &lt;/summary&gt; 
          [DataMember]
          public BCCollection&lt;string&gt; tags {
              get {
                  if (_tags == null) {
                      _tags = new BCCollection&lt;string&gt;();
                  }
                  return _tags;
              }
              set {
                  _tags = value;
              }
          }
  
          private BCCollection&lt;BCCuePoint&gt; _cuePoints;
  
          /// &lt;summary&gt;
          /// A list of cuePoints representing the cue points assigned to this Video.
          /// &lt;/summary&gt; 
          [DataMember]
          public BCCollection&lt;BCCuePoint&gt; cuePoints {
              get {
                  if(_cuePoints == null){
                      _cuePoints = new BCCollection&lt;BCCuePoint&gt;();
                  }
                  return _cuePoints;
              }
              set {
                  _cuePoints = value;
              }
          }
  
    /// &lt;summary&gt;
    /// The URL to the video still image associated with this Video. Video stills are 480x360 pixels.
    /// &lt;/summary&gt; 
    [DataMember]
    public string videoStillURL { get; set; }
  
    /// &lt;summary&gt;
    /// The URL to the thumbnail image associated with this Video. Thumbnails are 120x90 pixels.
    /// &lt;/summary&gt; 
    [DataMember]
    public string thumbnailURL { get; set; }
  
    /// &lt;summary&gt;
    /// A user-specified id that uniquely identifies this Video. ReferenceID can be used as a foreign-key to identify this video in another system. 
    /// &lt;/summary&gt; 
    [DataMember]
    public string referenceId { get; set; }
  
    /// &lt;summary&gt;
    /// The length of this video in milliseconds.
    /// &lt;/summary&gt; 
    [DataMember]
    public string length { get; set; }
  
    [DataMember(Name = "economics")]
    private string ecs { get; set; }
  
    /// &lt;summary&gt;
    /// Either FREE or AD_SUPPORTED. AD_SUPPORTED means that ad requests are enabled for this Video.
    /// &lt;/summary&gt; 
    public BCVideoEconomics economics {
     get {
      if (ecs == null) {
       return BCVideoEconomics.AD_SUPPORTED;
      }
      else if (ecs.Equals(BCVideoEconomics.AD_SUPPORTED.ToString())) {
       return BCVideoEconomics.AD_SUPPORTED;
      }
      else if (ecs.Equals(BCVideoEconomics.FREE.ToString())) {
       return BCVideoEconomics.FREE;
      }
      else {
       return BCVideoEconomics.AD_SUPPORTED;
      }
     }
     set {
      ecs = value.ToString();
     }
    }
  
    [DataMember(Name = "playsTotal")]
    private string plays { get; set; }
  
    /// &lt;summary&gt;
    /// How many times this Video has been played since its creation.
    /// &lt;/summary&gt; 
    public long playsTotal {
     get {
      if (!String.IsNullOrEmpty(plays)) {
       return long.Parse(plays);
      } else {
       return 0;
      }
     }
     set {
      plays = value.ToString();
     }
    }
  
    [DataMember(Name = "playsTrailingWeek")]
    private string playsWeek { get; set; }
  
          public static List&lt;string&gt; VideoFields {
              get {
                  List&lt;string&gt; fields = new List&lt;string&gt;();
                  foreach (string s in Enum.GetNames(typeof(BrightcoveSDK.VideoFields))) {
                      fields.Add(s);
                  }
                  return fields;
              }
          }
  
    /// &lt;summary&gt;
    /// How many times this Video has been played within the past seven days, exclusive of today.
    /// &lt;/summary&gt; 
    public long playsTrailingWeek {
     get {
      if(!String.IsNullOrEmpty(playsWeek)) {
       return long.Parse(playsWeek);
      } else {
       return 0;
      }
     }
     set {
      playsWeek = value.ToString();
     }
    }
  
          [DataMember(Name = "itemState")]
          private string _itemState {get; set;}
  
          public ItemStateEnum itemState {
              get {
      if (_itemState == null) {
       return ItemStateEnum.ACTIVE;
      }
      else if (_itemState.Equals(ItemStateEnum.ACTIVE.ToString())) {
       return ItemStateEnum.ACTIVE;
      }
      else if (_itemState.Equals(ItemStateEnum.DELETED.ToString())) {
       return ItemStateEnum.DELETED;
      }
                  else if (_itemState.Equals(ItemStateEnum.INACTIVE.ToString())) {
       return ItemStateEnum.INACTIVE;
      }
      else {
       return ItemStateEnum.ACTIVE;
      }
     }
     set {
      ecs = value.ToString();
     }
          }
  
          [DataMember(Name = "version")]
          private string _version {get; set;}
  
          public long version {
           get {
      if (!String.IsNullOrEmpty(_version)) {
       return long.Parse(_version);
      } else {
       return 0;
      }
     }
     set {
      _version = value.ToString();
     }
          }
  
          [DataMember]
          public string submissionInfo {get; set;}
  
          public CustomFields _customFields;
  
          [DataMember]
          public CustomFields customFields {
              get {
                  if (_customFields == null) {
                      _customFields = new CustomFields();
                  }
                  return _customFields;
              }
              set {
                  _customFields = value;
              }
          }
  
          [DataMember]
          public string releaseDate {get; set;}
  
          [DataMember]
          public string geoFiltered {get; set;}
  
          [DataMember]
          public string geoRestricted {get; set;}
  
          [DataMember]
          public string geoFilterExclude {get; set;}
  
          [DataMember]
          public string excludeListedCountries {get; set;}
  
          private BCCollection&lt;string&gt; _geoFilteredCountries;
  
          [DataMember]
          public BCCollection&lt;string&gt; geoFilteredCountries {
              get {
                  if (_geoFilteredCountries == null) {
                      _geoFilteredCountries = new BCCollection&lt;string&gt;();
                  }
                  return _geoFilteredCountries;
              }
              set {
                  _geoFilteredCountries = value;
              }
          }
  
          private BCCollection&lt;string&gt; _allowedCountries;
  
          [DataMember]
          public BCCollection&lt;string&gt; allowedCountries {
              get {
                  if (_allowedCountries == null) {
                      _allowedCountries = new BCCollection&lt;string&gt;();
                  }
                  return _allowedCountries;
              }
              set {
                  _allowedCountries = value;
              }
          }
  
          [DataMember(Name = "accountId")]
          private string _accountId {get; set;}
  
          public long accountId {
           get {
      if (!String.IsNullOrEmpty(_accountId)) {
       return long.Parse(_accountId);
      } else {
       return 0;
      }
     }
     set {
      _accountId = value.ToString();
     }
          }
  
    public BCVideo() {
    }
  
    #region IComparable Comparators
  
    public int CompareTo(BCVideo other) {
     return name.CompareTo(other.name);
    }
  
    //CREATION_DATE
    public static Comparison&lt;BCVideo&gt; CreationDateComparison =
     delegate(BCVideo v1, BCVideo v2)
     {
      return v1.creationDate.CompareTo(v2.creationDate);
     };
  
    //PLAYS_TOTAL
    public static Comparison&lt;BCVideo&gt; TotalPlaysComparison =
     delegate(BCVideo v1, BCVideo v2)
     {
      return v1.playsTotal.CompareTo(v2.playsTotal);
     };
  
    //PUBLISH_DATE
    public static Comparison&lt;BCVideo&gt; PublishDateComparison =
     delegate(BCVideo v1, BCVideo v2)
     {
      return v1.publishedDate.CompareTo(v2.publishedDate);
     };
  
    //MODIFIED_DATE
    public static Comparison&lt;BCVideo&gt; ModifiedDateComparison =
     delegate(BCVideo v1, BCVideo v2)
     {
      return v1.lastModifiedDate.CompareTo(v2.lastModifiedDate);
     };
  
    //PLAYS_TRAILING_WEEK
    public static Comparison&lt;BCVideo&gt; PlaysTrailingComparison =
     delegate(BCVideo v1, BCVideo v2)
     {
      return v1.playsTrailingWeek.CompareTo(v2.playsTrailingWeek);
     };
  
    #endregion
   }
  
   public static class BCVideoExtensions {
  
    #region Extension Methods
  
    public static string ToCreateJSON(this BCVideo video) {
     return ToJSON(video, JSONType.Create);
    }
  
    public static string ToJSON(this BCVideo video) {
     return ToJSON(video, JSONType.Update);
    }
  
          private static string ToJSON(this BCVideo video, JSONType type) {
  
     //--Build Video in JSON -------------------------------------//
  
              StringBuilder jsonVideo = new StringBuilder();
              jsonVideo.Append("{");
  
     if(type.Equals(JSONType.Update)){
      //id
      jsonVideo.Append("\"id\": " + video.id.ToString() + ",");
     }
  
     //name
     if (!string.IsNullOrEmpty(video.name)) {
      jsonVideo.Append("\"name\": \"" + video.name + "\"");
     }
  
     //shortDescription
     if (!string.IsNullOrEmpty(video.shortDescription)) {
      jsonVideo.Append(",\"shortDescription\": \"" + video.shortDescription + "\"");
     }
  
     //Tags should be a list of strings
     if (video.tags.Count &gt; 0) {
      jsonVideo.Append(",\"tags\": [");
      string append = "";
      foreach (string tag in video.tags) {
       jsonVideo.Append(append + "\"" + tag + "\"");
       append = ",";
      }
      jsonVideo.Append("]");
     }
  
     //referenceId
     if (!string.IsNullOrEmpty(video.referenceId)) {
      jsonVideo.Append(",\"referenceId\": \"" + video.referenceId + "\"");
     }
  
     //longDescription
     if (!string.IsNullOrEmpty(video.longDescription)) {
      jsonVideo.Append(",\"longDescription\": \"" + video.longDescription + "\"");
     }
  
              if (video.cuePoints.Count &gt; 0) {
                  jsonVideo.Append(",\"cuePoints\": " + video.cuePoints.ToJSON());
              }
  
     //economics
     jsonVideo.Append(",\"economics\": " + video.economics.ToString());
  
     jsonVideo.Append("}");
  
     return jsonVideo.ToString();
    }
  
    #endregion
   }
  }
  </code></pre>
  
  <p>CustomFields:</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Runtime.Serialization;
  
  namespace BrightcoveSDK
  {
      [CollectionDataContract]
      public class CustomFields : Dictionary&lt;string, string&gt;
      { }
  }
  </code></pre>