JObject tostring formatting issue for JArray

 ̄綄美尐妖づ 提交于 2021-01-07 01:29:33

问题


I have a question or rather an issue with the JObject. This is just a small example, I have large lists with more than 20 elements and I am saving these in JSON format and it is really bad to read if every value is in a new line. Can someone explain to me how to fix this?

Code:

var myObj = new 
{
    Vector = new List<int>{
        1,2,3,4,5
    }
};

Console.WriteLine(JToken.FromObject(myObj).ToString(Formatting.Indented));

Output is like this:

{
  "Vector": [
    1,
    2,
    3,
    4,
    5
  ]
}

But I want it to be like this:

{
  "Vector": [1,2,3,4,5]
}

I already tried to override the ToString() from MyObj but it doesn't work either.


回答1:


There is no method to control the formatting of specific nested tokens inside a JToken hierarchy when writing to JSON. Thus we will need to roll our own:

public static partial class JsonExtensions
{
    public static string ToFormattedString(this JToken token, params JsonConverter[] converters)
    {
        if (token == null)
            throw new ArgumentNullException();
        using (var sw = new StringWriter(CultureInfo.InvariantCulture))
        {
            using (var jw = new JsonTextWriter(sw) { Formatting = Formatting.Indented })
                FormattedWriteTo(token, jw, 0, converters);
            return sw.ToString();
        }
    }

    static void FormattedWriteTo(JToken token, JsonTextWriter writer, int depth, params JsonConverter[] converters)
    {
        if (token == null)
        {
            writer.WriteNull();
        }
        else if (token is JObject obj)
        {
            IList<JToken> asList = obj;
            writer.WriteStartObject();
            for (int i = 0, n = asList.Count; i < n; i++)
                FormattedWriteTo(asList[i], writer, depth+1, converters);
            writer.WriteEndObject();                
        }
        else if (token is JArray array)
        {
            // Disable formatting for arrays.  
            // You could smarten this up further by e.g. checking to see whether the array contents are all primitive JValue tokens.
            var old = writer.Formatting;
            // The question requires an extra space between the property name and the array value.
            if (depth > 0 && old == Formatting.Indented)
                writer.WriteWhitespace(" ");
            writer.Formatting = Formatting.None;
            writer.WriteStartArray();
            for (int i = 0, n = array.Count; i < n; i++)
                FormattedWriteTo(array[i], writer, depth+1, converters);
            writer.WriteEndArray();
            writer.Formatting = old;
        }
        else if (token is JProperty property)
        {
            writer.WritePropertyName(property.Name);
            FormattedWriteTo(property.Value, writer, depth+1, converters);
        }
        else
        { 
            // JValue, JRaw, JConstructor
            token.WriteTo(writer);
        }
    }
}

Then JToken.FromObject(myObj).ToFormattedString() produces, as required:

{
  "Vector": [1,2,3,4,5]
}

Notes:

  • If you were serializing myObj directly you would be able to use a custom JsonConverter for the List<int> to disable formatting, as shown in How to apply indenting serialization only to some properties? and Newtonsoft inline formatting for subelement while serializing. But because you are writing an already-serialized JToken hierarchy, the serializer is not invoked and a custom converter for arrays will not be called.

Demo fiddle here.



来源:https://stackoverflow.com/questions/65304693/jobject-tostring-formatting-issue-for-jarray

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!