239

I have an object model that looks like this:

public MyObjectInJson
{
   public long ObjectID {get;set;}
   public string ObjectInJson {get;set;}
}

The property ObjectInJson is an already serialized version an object that contains nested lists. For the moment, I'm serializing the list of MyObjectInJson manually like this:

StringBuilder TheListBuilder = new StringBuilder();

TheListBuilder.Append("[");
int TheCounter = 0;

foreach (MyObjectInJson TheObject in TheList)
{
  TheCounter++;
  TheListBuilder.Append(TheObject.ObjectInJson);

  if (TheCounter != TheList.Count())
  {
    TheListBuilder.Append(",");
  }
}
TheListBuilder.Append("]");

return TheListBuilder.ToString();

I wonder if I can replace this sort of dangerous code with JavascriptSerializer and get the same results. How would I do this?

janw
  • 8,758
  • 11
  • 40
  • 62
frenchie
  • 51,731
  • 109
  • 304
  • 510
  • Note that in a WPF project, you need to add a reference to `System.Web.Extensions` to use `System.Web.Script.Serialization`: https://stackoverflow.com/a/18746092/1599699 https://stackoverflow.com/a/19299695/1599699 – Andrew Jun 28 '18 at 14:45

9 Answers9

445

If using .Net Core 3.0 or later;

Default to using the built in System.Text.Json parser implementation.

e.g.

using System.Text.Json;

var json = JsonSerializer.Serialize(aList);

alternatively, other, less mainstream options are available like Utf8Json parser and Jil: These may offer superior performance, if you really need it but, you will need to install their respective packages.

If stuck using .Net Core 2.2 or earlier;

Default to using Newtonsoft JSON.Net as your first choice JSON Parser.

e.g.

using Newtonsoft.Json;

var json = JsonConvert.SerializeObject(aList);

you may need to install the package first.

PM> Install-Package Newtonsoft.Json

For more details see and upvote the answer that is the source of this information.

For reference only, this was the original answer, many years ago;

// you need to reference System.Web.Extensions

using System.Web.Script.Serialization;

var jsonSerialiser = new JavaScriptSerializer();
var json = jsonSerialiser.Serialize(aList);
Jodrell
  • 34,946
  • 5
  • 87
  • 124
123

You can also use Json.NET. Just download it at http://james.newtonking.com/pages/json-net.aspx, extract the compressed file and add it as a reference.

Then just serialize the list (or whatever object you want) with the following:

using Newtonsoft.Json;

string json = JsonConvert.SerializeObject(listTop10);

Update: you can also add it to your project via the NuGet Package Manager (Tools --> NuGet Package Manager --> Package Manager Console):

PM> Install-Package Newtonsoft.Json

Documentation: Serializing Collections

James Newton-King
  • 48,174
  • 24
  • 109
  • 130
Brent Barbata
  • 3,631
  • 3
  • 24
  • 23
13

There are two common ways of doing that with built-in JSON serializers:

  1. JavaScriptSerializer

    var serializer = new JavaScriptSerializer();
    return serializer.Serialize(TheList);
    
  2. DataContractJsonSerializer

    var serializer = new DataContractJsonSerializer(TheList.GetType());
    using (var stream = new MemoryStream())
    {
        serializer.WriteObject(stream, TheList);
        using (var sr = new StreamReader(stream))
        {
            return sr.ReadToEnd();
        }
    }
    

    Note, that this option requires definition of a data contract for your class:

    [DataContract]
    public class MyObjectInJson
    {
       [DataMember]
       public long ObjectID {get;set;}
       [DataMember]
       public string ObjectInJson {get;set;}
    }
    
skink
  • 5,133
  • 6
  • 37
  • 58
6
public static string JSONSerialize<T>(T obj)
        {
            string retVal = String.Empty;
            using (MemoryStream ms = new MemoryStream())
            {
                DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType());
                serializer.WriteObject(ms, obj);
                var byteArray = ms.ToArray();
                retVal = Encoding.UTF8.GetString(byteArray, 0, byteArray.Length);
            }
            return retVal;
        }
5

.NET already supports basic Json serialization through the System.Runtime.Serialization.Json namespace and the DataContractJsonSerializer class since version 3.5. As the name implies, DataContractJsonSerializer takes into account any data annotations you add to your objects to create the final Json output.

That can be handy if you already have annotated data classes that you want to serialize Json to a stream, as described in How To: Serialize and Deserialize JSON Data. There are limitations but it's good enough and fast enough if you have basic needs and don't want to add Yet Another Library to your project.

The following code serializea a list to the console output stream. As you see it is a bit more verbose than Json.NET and not type-safe (ie no generics)

        var list = new List<string> {"a", "b", "c", "d"};

        using(var output = Console.OpenStandardOutput())                
        {                
            var writer = new DataContractJsonSerializer(typeof (List<string>));
            writer.WriteObject(output,list);
        }

On the other hand, Json.NET provides much better control over how you generate Json. This will come in VERY handy when you have to map javascript-friendly names names to .NET classes, format dates to json etc.

Another option is ServiceStack.Text, part of the ServicStack ... stack, which provides a set of very fast serializers for Json, JSV and CSV.

Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236
1

building on an answer from another posting.. I've come up with a more generic way to build out a list, utilizing dynamic retrieval with Json.NET version 12.x

using Newtonsoft.Json;

static class JsonObj
{
    /// <summary>
    /// Deserializes a json file into an object list
    /// Author: Joseph Poirier 2/26/2019
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="fileName"></param>
    /// <returns></returns>
    public static List<T> DeSerializeObject<T>(string fileName)
    {
        List<T> objectOut = new List<T>();

        if (string.IsNullOrEmpty(fileName)) { return objectOut; }

        try
        {
            // reading in full file as text
            string ss = File.ReadAllText(fileName);

            // went with <dynamic> over <T> or <List<T>> to avoid error..
            //  unexpected character at line 1 column 2
            var output = JsonConvert.DeserializeObject<dynamic>(ss);

            foreach (var Record in output)
            {
                foreach (T data in Record)
                {
                    objectOut.Add(data);
                }
            }
        }
        catch (Exception ex)
        {
            //Log exception here
            Console.Write(ex.Message);
        }

        return objectOut;
    }
}

call to process

{
        string fname = "../../Names.json"; // <- your json file path

        // for alternate types replace string with custom class below
        List<string> jsonFile = JsonObj.DeSerializeObject<string>(fname);
}

or this call to process

{
        string fname = "../../Names.json"; // <- your json file path

        // for alternate types replace string with custom class below
        List<string> jsonFile = new List<string>();
        jsonFile.AddRange(JsonObj.DeSerializeObject<string>(fname));
}
Joseph Poirier
  • 386
  • 2
  • 17
1

If you're doing this in the context of a asp.Net Core API action, the conversion to Json is done implicitly.

[HttpGet]
public ActionResult Get()
{
    return Ok(TheList);
}
Giles Roberts
  • 6,407
  • 6
  • 48
  • 63
1
using System;
  using System.Text.Json;   
  using System.Collections.Generic;

    public class Program
    {
        public static void Main()
        {
            
            List<ErrorDetail>  aList = new List<ErrorDetail>();
            ErrorDetail a = new  ErrorDetail{ ColumnName="aaa", ErrorText="abbbb"};
            ErrorDetail c = new  ErrorDetail{ ColumnName="ccc", ErrorText="cccc"};
            ErrorDetail b = new  ErrorDetail{ ColumnName="ccc", ErrorText="cccc"};
            aList.Add(a);
            aList.Add(b);
            aList.Add(c);
            
            var json = JsonSerializer.Serialize(aList);
            
            Console.WriteLine(json);
        }
        
        public class ErrorDetail
        {
           
            public string ColumnName { get; set; }
    
           
            public string ErrorText { get; set; }
    
    
    
    
        }
    }
SKARVA Bodavula
  • 903
  • 11
  • 17
0

I tried the other answers here to serialize parameters for a POST request, but my backend did not like the fact that I was sending up a string version of my array. I did not want to have to always check if the type of a parameter is a string and convert it to an array.

I'm using Json.NET (which is now built into C#), and I convert my List to an array and let the converter handle the rest.

public class MyObjectInJson 
{
    public long ID;
    public OtherObject[] array;
}

You can convert your List into an array using list.ToArray();

And then finally using the JsonConvert, you can turn the entire object into a string:

string jsonString = JsonConvert.SerializeObject(objectInJson);

Hope this helps someone else.

kbunarjo
  • 1,277
  • 2
  • 11
  • 27