7

I have a problem with empty JSON lists deserializing to null while null values deserializes to an empty list.

Using this test scenario in a completely new MVC project:

public class TestController : Controller
{
   public ActionResult Index(ImportObject importObject)
   {
      return Content("Response");
   }

   public class ImportObject
   {
      public List<string> StringListNull { get; set; }
      public List<string> StringListEmpty { get; set; }
      public List<string> StringListPopulated { get; set; }
   }
}

I'm posting the following JSON:

{
  "StringListNull": null,
  "StringListEmpty": [],
  "StringListPopulated": ["one", "two"]
}

And this happens:

Debugging result

The populated string list is expected. But in my mind the null value of StringListNull should result in it being null.

When passing the value [] I'm expecting it being turned into an empty list

Am I missing something trivial? How can I make the null value become a nulled list and the empty list become an empty list?

What controls the default serialization from JSON to the parameter class (ImportObject)?

/K

5
  • First thing to check is if the names match exactly. If you misspelled the name of the variable at the caller (e.g. your Ajax), then this might happen, please check to be sure first. Commented May 15, 2019 at 12:30
  • Ah, I can see, your positions are switched. You pass StringListNull First in the JSON, but it is Second in the DTO class. Commented May 15, 2019 at 12:32
  • @st_stefanov StringListNull is first in both class and JSON Commented May 15, 2019 at 13:38
  • Ha weird, in the screen shot Visual Studio shows the other one as first. Sorry. Commented May 15, 2019 at 13:44
  • Ah, yes.. That's just the debugger sorting by name I guess! Commented May 15, 2019 at 14:14

2 Answers 2

1

I tried your code and works absolutely fine, probably you are switching the StringListNull and StringListEmpty.

enter image description here

Here is how I tested it, try it out and see where you are making something wrong:

public class ImportObject
{
    public List<string> StringListNull { get; set; }
    public List<string> StringListEmpty { get; set; }
    public List<string> StringListPopulated { get; set; }
}


class Program
{
    static void Main(string[] args)
    {
        var sb = new StringBuilder();
        var line = string.Empty;

        while (!string.IsNullOrWhiteSpace((line = Console.ReadLine())))
        {
            sb.AppendLine(line);
        }

        var json = sb.ToString().Trim();
        var inputObj = JsonConvert.DeserializeObject<ImportObject>(json);

        Console.WriteLine();
    }
}

This is a simple Console app to test your logic. Edit: tested with your input JSON:

{
  "StringListNull": null,
  "StringListEmpty": [],
  "StringListPopulated": ["one", "two"]
}
Sign up to request clarification or add additional context in comments.

4 Comments

How could I possibly switch them? You see the ImportObject and the JSON, that's it..
That's a really good question. Did you try to test it again with the given JSON? A possible case is that you switched the values in the JSON like this: { "StringListEmpty": null, "StringListNull": [], "StringListPopulated": ["one", "two"] }
Write back if this is not the case. Hope it helps. Cheers
This does not help, I'm using the json as it's written in the question..
1

Well, you can use Newtonsoft.Json or Json.NET for serializing or deserializing the Json. It will give you the required results.

This is the code I tried with it:

static void Convert()
{
    string K = @"{ ""StringListNull"": null, ""StringListEmpty"": [], ""StringListPopulated"": [""one"", ""two""]}";
    var list= JsonConvert.DeserializeObject<ImportObject>(K);
}

public class ImportObject
{
    public List<string> StringListNull { get; set; }
    public List<string> StringListEmpty { get; set; }
    public List<string> StringListPopulated { get; set; }
}

And in the list object is exactly as you want.

1 Comment

I was hoping to avoid using a separate Deserialize and just use the ImportObject as a parameter for the endpoint in the controller as in my example..

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.