Solving “No parameterless constructor defined for type of ‘System.String’.”

TL;DR

If you have the problem

No parameterless constructor defined for type of ‘System.String’!

just add the DeserializeObject and InterceptError functions , add this 2 lines:

var obj = new JavaScriptSerializer().Deserialize<Dictionary<string, object>>(json); //json parameter is the string content of the api
<your object> = DeserializeObject(obj, typeof(<your object type>)) as <your object type>; 

watch the debug window and you will see the problems marked with !!!
( See also video at http://youtu.be/7oZ37pnSNtM)

Long story:

I wanted to do a tutorial for obtaining data from foursquare from Web , Desktop and mobile applications. I have made some research first and I have discovered the API and a library for obtaining data.

Unfortunately, foursquare changed his API and , when deserializing, the application was giving  

“No parameterless constructor defined for type of ‘System.String’.

 

at this line

fourSquareResponse = new JavaScriptSerializer().Deserialize<FourSquareSingleResponse<T>>(json);

I have made a custom code to see where the errors are. 

I do not want to explain the code, just look at it and then I will show how to use:

/// <summary>
        /// TODO: make this add to global errors to return to the caller
/// </summary>
        /// <param name="message"></param>
        private void InterceptError(string message)
        {
            var cc = Console.ForegroundColor;
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine(message);
            Console.ForegroundColor = cc;
            Debug.WriteLine(message);
        }
        private object DeserializeObject(Dictionary<string, object> dictItem, Type tip)
        {
            
            var newInstance = Activator.CreateInstance(tip);
            var isDictionary = (tip.GetInterface("IDictionary") != null);
            PropertyInfo p = null;
            foreach (var k in dictItem.Keys)
            {
                var ser=  new JavaScriptSerializer().Serialize(dictItem[k]);

                
                Type tipP = null;
                if (isDictionary)
                {
                    tipP = tip.GetGenericArguments()[1];
                }
                else
                {
                    
                    try
                    {
                        p = tip.GetProperty(k);
                        if (p == null)
                            throw new ArgumentNullException(k);
                    }
                    catch (Exception)
                    {
                        //Console.WriteLine(ex.Message);                        
                        InterceptError("missing property:" + k + " to class" + tip.FullName + " value:" + ser);
                        continue;
                    }
                    tipP = p.PropertyType;
                }
                
                
                if (tipP.IsClass && tipP.FullName != typeof(string).FullName)
                {
                    
                    dynamic val = null;
                    try
                    {
                        val = new JavaScriptSerializer().Deserialize(ser, tipP);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("error for class:" + k + ex.Message);
                        IList arr = dictItem[k] as object[];
                        if (arr == null)
                        {
                            arr = dictItem[k] as ArrayList;
                        }
                        if (arr == null)
                        {                            
                            var t1 = dictItem[k] as Dictionary<string, object>;
                            if (t1 == null)
                            {
                                InterceptError("Not a dictionary, not an array - please contact ignatandrei@yahoo.com for " + k);
                            }

                            val = DeserializeObject(dictItem[k] as Dictionary<string, object>, tipP);
                            
                        }
                        else
                        {
                            val = Activator.CreateInstance(tipP);
                            var tipGen=tipP.GetGenericArguments()[0];
                            foreach (var obj in arr)
                            {
                                val.Add((dynamic)DeserializeObject(obj as Dictionary<string, object>, tipGen));
                            }
                        }
                        

                    }

                    if (isDictionary)
                    {
                        ((IDictionary)newInstance).Add(k, Convert.ChangeType(val, tipP));
                    }
                    else
                    {
                        p.SetValue(newInstance, Convert.ChangeType(val, tipP), null);

                    }
                }
                else//simple int , string, 
                {
                    try
                    {
                        if (isDictionary)
                        {
                            ((IDictionary)newInstance).Add(k, Convert.ChangeType(dictItem[k], tipP));
                        }
                        else
                        {
                            p.SetValue(newInstance, Convert.ChangeType(dictItem[k], tipP), null);
                        }
                    }
                    catch (Exception ex)
                    {
                        InterceptError("!!!not a simple property " + k + " from " + tip + " value:" + ser);
                    }
                }
            }
            return newInstance;
        }

Now the original code that throws the error looks this way:

try
            {
                fourSquareResponse = new JavaScriptSerializer().Deserialize<FourSquareSingleResponse<T>>(json);  //json parameter is the string content of the api
            }
            catch (Exception ex)
            {
                var obj = new JavaScriptSerializer().Deserialize<Dictionary<string, object>>(json);  //json parameter is the string content of the api
                fourSquareResponse = DeserializeObject(obj, typeof(FourSquareSingleResponse<T>)) as FourSquareSingleResponse<T>; 
            }

When looking to the debug window, you will see:

!!!not a simple property icon from FourSquare.SharpSquare.Entities.Category value:{"prefix":"https://ss1.4sqi.net/img/categories_v2/building/home_","suffix":".png"}

 

If looking to the source code, you will see

public string icon
        {
            get;
            set;
        }

And in the foursquare api you will see

 

    • icon: {
      • prefix: "https://ss1.4sqi.net/img/categories_v2/travel/trainstation_"
      • suffix: ".png"

      }

  •  

    Now it is clear : icon is not a string, is a class!
    So just add a class with required properties , modify the property from string to this class and it is all solved!
    ( for me, the class is:

       public class Icon
       {
           public string prefix { get; set; }
           public string suffix { get; set; }
    
        }
    

    and the definition will be:

    public Icon icon
            {
                get;
                set;
            }
    

    Moral of the story:

    When obtaining data via HTTP API, just be sure that you can handle modifications!