Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
74 views
in Technique[技术] by (71.8m points)

c# - How to transform an object during conversion to json?

I have a flat DTO object with ~500 fields that is returned via an API call. The .NET machinery converts it to JSON and all is good. It looks like this:

{
  "id": 1,
  "desc": "foo",
  "system": "axmls",
  "bedrooms": 5,
  "flooring": "tile",
  "roof": "tesla",
  ...
  ...
}

Now I am being asked to place these ~500 fields into categories to make it look similar to this:

{
  "main": {
    "id": 1,
    "desc": "foo",
    "system": "axmls",
    ...
  }
  "interior": {
    "bedrooms": 5,
    "flooring": "tile",
    ...
  }
  "exterior": {
    "roof": "tesla",
    ...
  }
}

I've thought of couple of ways to doing this (none too enticing)

  1. Create a new object to match this structure and copy data to it. Not great.
  2. Build JSON by hand. No.
  3. Mark each field on the original object with a Category attribute and then somehow in a FilterAttribute transform it. This one sounds most promising, though I am not sure how to implement it.

Is there a way to create a JSON structure like this in a sane manner?

question from:https://stackoverflow.com/questions/65617529/how-to-transform-an-object-during-conversion-to-json

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Here's what I described in the comments. First, you need some metadata. I use an enum here (since it makes typos less likely - though it does make the code ever so slightly more complicated.

(UPDATE: I found a bug, I was treating everything as strings. now I treat the leaf nodes of the trees as object)

First the category types:

private enum CategoryName
{
    Main,
    Interior,
    Exterior,
}

and the category metadata:

private static readonly Dictionary<string, CategoryName> _categoryMetadata =
    new Dictionary<string, CategoryName>
    {
        {"id", CategoryName.Main},
        {"desc", CategoryName.Main},
        {"system", CategoryName.Main},
        {"bedrooms", CategoryName.Interior},
        {"flooring", CategoryName.Interior},
        {"roof", CategoryName.Exterior}
    };

Now, your input JSON. Note that I single-quoted the strings, it makes it easier to use in C# and doesn't change the nature of the JSON. I also took out all your ... entries:

 private const string InputJson = @"
 {
     'id': 1,
     'desc': 'foo',
     'system': 'axmls',
     'bedrooms': 5,
     'flooring': 'tile',
     'roof': 'tesla',
 }";

Finally the code. As I described in the comments "Build a metadata dictionary (string, string) that maps each item (bedrooms, flooring, roof) to categories (main, interior, exterior). Read the data you have (the big initial list) into a Dictionary<string, string>. Then walk that Dictionary, looking up the category in the metadata. Finally populate a Dictionary<string, Dictionary<string, string>> with the results and serialize it back out to JSON":

var output = new Dictionary<string, Dictionary<string, object>>();
var input = JsonConvert.DeserializeObject<Dictionary<string, object>>(InputJson);
foreach (var item in input)
{
    if (_categoryMetadata.TryGetValue(item.Key, out var category))
    {
        var categoryString = category.ToString().ToLower();
        if (!output.ContainsKey(categoryString))
        {
            output[categoryString] = new Dictionary<string, object>();
        }

        output[categoryString].Add(item.Key, item.Value);
    }
}

var result = JsonConvert.SerializeObject(output, Formatting.Indented);

When that's finished (and after my update), the JSON looks like:

{
  "main": {
    "id": 1,
    "desc": "foo",
    "system": "axmls"
  },
  "interior": {
    "bedrooms": 5,
    "flooring": "tile"
  },
  "exterior": {
    "roof": "tesla"
  }
}

In real life, you'd remove the Formatting.Indented parameter on the JsonConvert.Serialize call.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...