I would like to serialize (and deserialize) an C# object to a json string.
Normally when objects are serialized, objects are enclosed in a pair of {}
in the generated json.
But here I am interested in object to be serialized to only a string.
I am interested in doing this to encapsulate logic about how ItemNumber
s should be formatted.
But I am not interested expose the fact that I am using a class for the ItemNumber
instead of an ordinary string.
Here is an example of what I am looking for.
The class ItemNumber
is contained in the class Item
.
public class ItemNumber
{
private string _value;
public ItemNumber(string num)
{
_value = num;
}
}
public class Item
{
public ItemNumber ItemNumber { get; set; }
}
public void Main()
{
var itemNumber = new ItemNumber("ABC-1234");
var item = new Item
{
ItemNumber = itemNumber,
};
var json = System.Text.Json.JsonSerializer.Serialize(item);
}
I would like for an Item
to be serialized to json looking like this:
{
"itemNumber": "ABC-1234" // <- Notice, not an object. Just a string
}
I understand that I probably have to implement custom serializer, but the guide have found seems to assume that a C# object should always be serialized to a json object.
How do implement the serialization logic I am looking for?
CodePudding user response:
The answer for how to do this is explained in the System.Text.Json documentation. Implement a custom converter and use that during serialization.
Note: it is not possible to extract the value from ItemNumber
in your example, I implemented the ToString
method.
public class ItemNumber
{
private string _value;
public ItemNumber(string num)
{
_value = num;
}
public override string ToString()
{
return _value;
}
}
public class Item
{
// rename output property
[JsonPropertyName("itemNumber")]
// use custom converter
[JsonConverter(typeof(ItemNumberJsonConverter))]
public ItemNumber ItemNumber { get; set; }
}
public class ItemNumberJsonConverter : JsonConverter<ItemNumber>
{
public override ItemNumber Read(
ref Utf8JsonReader reader,
Type typeToConvert,
JsonSerializerOptions options) =>
new ItemNumber(reader.GetString()!);
public override void Write(
Utf8JsonWriter writer,
ItemNumber val,
JsonSerializerOptions options) => writer.WriteStringValue(val.ToString());
}
internal class Program
{
static void Main(string[] args)
{
var itemNumber = new ItemNumber("ABC-1234");
var item = new Item
{
ItemNumber = itemNumber,
};
var serializeOptions = new JsonSerializerOptions
{
WriteIndented = true,
};
var json = System.Text.Json.JsonSerializer.Serialize(item, serializeOptions);
Console.WriteLine(json);
}
}
console output
{
"itemNumber": "ABC-1234"
}
CodePudding user response:
you will not need any custom serialiazers, if you add some attributes to your classes
public class Item
{
[System.Text.Json.Serialization.JsonIgnore]
public ItemNumber ItemNumber { get; set; }
[System.Text.Json.Serialization.JsonPropertyName("itemNumber")]
public string _itemNumberValue
{
get { return ItemNumber==null? null: ItemNumber.ToString(); }
set {ItemNumber = new ItemNumber(value);}
}
public Item(string itemNumber)
{
ItemNumber = new ItemNumber(itemNumber);
}
public Item() { }
}
CodePudding user response:
I dont know why you wont just do this???
Add ?
if you want to allow the values of the object to be nullable.
public class ItemNumber
{
public string? Number { get; set; }
public ItemNumber(string itemNumber)
{
this.Number = itemNumber;
}
}
public class Item
{
//Can be any data type / object
public int? ItemNumber { get; set; }
public List<int>? ItemNumbers { get; set; }
public ItemNumber? Number { get; set; }
}
and then...
//Where ever you're populating the object
var itemNumbers = new Item
{
ItemNumber = 1,
ItemNumbers = new List<int> { 1, 2, 3, 4 },
Number = new ItemNumber("ABC-1234")
};
//Write this output to a new file or and existing one to update it.
var output = JsonConvert.SerializeObject(itemNumbers);
/* Output
* {
* "ItemNumber": 1,
* "ItemNumbers": [1,2,3,4],
* "Number": {"Number":"ABC-1234"}
* }
*/
Edit: Would highly recommend using Newtonsoft.