将任何字段(对象类型)的Json对象转换为json对象数组

时间:2015-03-03 10:01:13

标签: c# json.net

我是C#的新手。我需要你的帮助。我在Oracle上有这样的json:

[
  {
    "id": 123,
    "name": "myname",
    "avatars":[
      {
        "id": 1
        "typeid": 500
      },
      {
        "id": 2
        "typeid": 600
      }
    ]    
  }
]

但是如果avatars数组只有一行,那么Oracle会返回如下的头像:

"avatars":{
    "avatars_ROW":
      {
        "id": 1
        "typeid": 500
      }
}

现在,头像是一个json对象,有一个字段_ROW,而不是json数组。

另外,我还有其他字段(数组):"roles", "accounts" ....

在C#中,我有所有列表,例如List<avatar>List<role> ...

我的问题:

如何找到object中的所有字段,其第一个字段的名称以&#34; _ROW&#34;结尾,并将它们从具有一个字段(对象)的对象转换为具有一个成员的对象数组?

感谢。

P.S。我无法更改Oracle的函数源代码。

2 个答案:

答案 0 :(得分:0)

可能有这个完全错误,但我认为你需要在序列化数据之前将其包装起来,如果你正在做的那样。

所以你需要一个List和In Account,当你将它序列化为json时,它会有一个List,它应该是你想要的格式。

如果你看一些包装的restsharp例子,我认为这会有所帮助。

答案 1 :(得分:0)

我无法改变“所需的格式”。 Oracle的函数为我返回json。
我创建了愚蠢的解决方案,但它确实有效:)这是我纠正json的功能:

// fix _ROW  in "pretty-print :)"  json text
static private String FixJson(String json)
{
    const String cRowString = "_ROW\" : {";      //  _ROW" : {"
    const String cEmpArrInvalid = "\" : \"\\n  \""; //  " : "\  "
    const String cEmpArrNormaly = "\":[]";          //  ":[]

    var lines = json.Split(new string[] { Environment.NewLine }, StringSplitOptions.None); // json-string to string array. delimiter = NewLine
    for (var i = 0; i < lines.Count(); i++) // loop strings
    {
        var line = lines[i]; // current string

        // oracle return json array with count=0 as "blabla": "\ ". I need "blabla": []
        char[] charsToTrim = { ',' };
        if (line.TrimEnd(charsToTrim).EndsWith(cEmpArrInvalid)) // find jarray-value with 0 elements. fucking Oracle's function :)
        {
            lines[i] = line.Replace(cEmpArrInvalid, cEmpArrNormaly); // replace bad substring( "\  " ) on empty array( [] )
            continue; // next string
        }

        if (!line.Contains(cRowString)) continue; // if not bad-string  => next string

        lines[i - 1] = lines[i - 1].Replace("{", "["); // _ROW found => in prev string replace object's start ( { ) on array's start ( [ )
        var pStart = line.IndexOf("\"", StringComparison.CurrentCulture); // find start position of field ( " )

        var sFind = ""; // string to search for end of object = backspace*pStart + }
        for (var k = 0; k < pStart; k++)
            sFind = sFind + ' ';
        sFind = sFind + '}';

        lines[i] = "{"; // replace singl-row property "blablabla_ROW": {   on start of object ( { )

        for (var j = i + 1; j < lines.Count(); j++) // from next line, find end of object. and replace object's end on array's end
        {
            if (!lines[j].StartsWith(sFind)) continue;  // if not end of object then next string

            lines[j + 1] = lines[j + 1].Replace("}", "]"); // found ! replace object's end on array's end
            break; // break loop
        }
    }

    return String.Join(Environment.NewLine, lines); // join string array into one string with newline-separator
}

但是想通过库json.net解决这个问题,而不是解析\更改行。

我解决了这个问题。我的功能:

private static void FixJObj(JToken jt)
{

    if (jt.GetType() == typeof (JArray))
    {
        foreach (var item in (JArray) jt)
        {
            FixJObj(item);
        }
        return;
    }

    if (jt.GetType() != typeof(JObject)) return;

    var jo = (JObject) jt;

    foreach (var jField in jo) // loop in object fields
    {
        if (jField.Value.ToString() == "\n  ") // if field value = "\n "
        {
            jField.Value.Replace(new JArray()); // replace "\n " with empty array [] 
            continue;
        }

        if (  !jField.Value.Any()  ) continue;

        FixJObj(jField.Value); // fix cur obj field recursive

        var jFirstField = jField.Value.First; // get first field
        if ( jFirstField.GetType() != typeof(JProperty) ) continue; // if its property

        var jProp = ((JProperty)jFirstField);

        if ( !jProp.Name.EndsWith("_ROW") ) continue;

        jField.Value.Replace(new JArray { jProp.Value });
    }
}
相关问题