33

I have class with some internal properties and I would like to serialize them into json as well. How can I accomplish this? For example

public class Foo
{
    internal int num1 { get; set; }
    internal double num2 { get; set; }
    public string Description { get; set; }

    public override string ToString()
    {
        if (!string.IsNullOrEmpty(Description))
            return Description;

        return base.ToString();
    }
}

Saving it using

Foo f = new Foo();
f.Description = "Foo Example";
JsonSerializerSettings settings = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All };

 string jsonOutput = JsonConvert.SerializeObject(f, Formatting.Indented, settings);

 using (StreamWriter sw = new StreamWriter("json_file.json"))
 {
     sw.WriteLine(jsonOutput);
 }

I get

{  
"$type": "SideSlopeTest.Foo, SideSlopeTest",
"Description": "Foo Example"
}
5
  • 4
    Usually internal properties are not intended to be leaving the boundaries of the current assembly and thus being serialized. Why would you need to do that? If you want a proper JSON representation you might need a DTO to map your internal/private stuff to and then serialize. Commented Nov 11, 2014 at 20:21
  • +1 what @DarinDimitrov said. But if you really want to do it, I believe you need to subclass DefaultContractResolver to make it look at non-public properties as well.
    – s.m.
    Commented Nov 11, 2014 at 20:24
  • 1
    possible duplicate of JSON.Net: Force serialization of all private fields and all fields in sub-classes
    – David L
    Commented Nov 11, 2014 at 20:25
  • 3
    Just mark them with the [JsonProperty()] attribute.
    – dbc
    Commented Nov 11, 2014 at 20:27
  • if the class is also internal mark it with [JsonObject()]
    – CAD bloke
    Commented Feb 19, 2018 at 13:23

1 Answer 1

53

Mark the internal properties to be serialized with the [JsonProperty] attribute:

public class Foo
{
    [JsonProperty]
    internal int num1 { get; set; }
    [JsonProperty]
    internal double num2 { get; set; }

    public string Description { get; set; }

    public override string ToString()
    {
        if (!string.IsNullOrEmpty(Description))
            return Description;

        return base.ToString();
    }
}

And then later, to test:

Foo f = new Foo();
f.Description = "Foo Example";
f.num1 = 101;
f.num2 = 202;
JsonSerializerSettings settings = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All };

var jsonOutput = JsonConvert.SerializeObject(f, Formatting.Indented, settings);

Console.WriteLine(jsonOutput);

I get the following output:

{
  "$type": "Tile.JsonInternalPropertySerialization.Foo, Tile",
  "num1": 101,
  "num2": 202.0,
  "Description": "Foo Example"
}

(Where "Tile.JsonInternalPropertySerialization" and "Tile" are namespace and assembly names I am using).

As an aside, when using TypeNameHandling, do take note of this caution from the Newtonsoft docs:

TypeNameHandling should be used with caution when your application deserializes JSON from an external source. Incoming types should be validated with a custom SerializationBinder when deserializing with a value other than None.

For a discussion of why this may be necessary, see TypeNameHandling caution in Newtonsoft Json and and External json vulnerable because of Json.Net TypeNameHandling auto?.

3
  • I just deleted my answer saying that internal properties are not accessible outside the assembly because this is news to me. How is a serializer able to access these across assemblies? Is this not somewhat of a security problem?
    – esmoore68
    Commented Apr 14, 2016 at 16:28
  • 5
    @esmoore68 - The serializer uses reflection. See e.g. stackoverflow.com/questions/1565734/… and stackoverflow.com/questions/30191282/….
    – dbc
    Commented Apr 14, 2016 at 16:34
  • in addition to @dbc answer, what is reported is still valid also for internal-visibility classes and private-visibility (nested) classes Commented Dec 22, 2021 at 11:17

Not the answer you're looking for? Browse other questions tagged or ask your own question.