Costomising the serialisation/serialised JSON in s

2019-07-11 05:09发布

问题:

I need to turn this beutifull default JSON from Service Stack :

{
      "Status": "ok",
      "LanguageArray": [{
      "Id": 1,
      "Name": "English"
      }, {
      "Id": 2,
      "Name": "Chinese"
      }, {
      "Id": 3,
      "Name": "Portuguese"
      }]
     }

To this monstrosity of abomination:

{"status":"ok","language":{
     "0":{"id":"1", "name":"English"},
     "1":{"id":"2", "name":"Chinese"},
     "2":{"id":"3", "name":"Portuguese"},
     }

For reasons beyond my control or ration or logic.

My question is what are the simplest way of achieving this? I need to do this to almost all Arrays ( they are IEnumerables implemented using List in C#)

回答1:

I don't think I have a 'simplest way' and it kind of depends on where you need the serialization to happen as well as how strict the format is (case sensitive?, spacing?)

If place your example text and turn it into classes like this

public class Language
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class OuterLanguage
{
    public string Status { get; set; }
    public IEnumerable<Language> LanguageArray { get; set; }
}

A pretty straightforward way would be having a Dto that adds a property for serialization of the Array and ignores the original Array.

public class OuterLanguageDto
{
    public string Status { get; set; }
    [IgnoreDataMember]
    public IEnumerable<Language> LanguageArray { get; set; }
    public IDictionary<string, Language> language 
    { 
        get { return this.LanguageArray.ToDictionary(x => (x.Id - 1).ToString()); } 
    }
}

When you need to serialize your class (OuterLanguage) you use TranslateTo (or your preferred Mapper) and copy the values over to the Dto.

var jsonObj = obj.TranslateTo<OuterLanguageDto>();
var jsonStr = new JsonSerializer<OuterLanguageDto>().SerializeToString(jsonObj);

You could also look into Custom Serialization. That would give you to have a way to serialize all your Arrays into the correct format.

JsConfig<IEnumerable<Language>>.SerializeFn = ToJson

private string ToJson(IEnumerable<Language> arr)
{
    var dict = arr.ToDictionary(x => x.Id - 1);

    var str = JsonSerializer.SerializeToString<Dictionary<int, Language>>(dict);

    return str;
}

However, I'm guessing you may have to do some "magic string work" to take your custom serialized Array's json string and format it properly when outer class (OuterLanguage in this example) is the one being serialized.