将typenameHandling json转换为常规json

时间:2017-07-16 15:31:27

标签: c# json.net

是否可以将JSON.NET生成的json转换为常规json的类型名称处理?

我的应用程序不能假设它正在接收的类型,因为它将是许多1000个类中的1个。我只需要从json中删除类型信息。

例如,我在我的应用程序中收到了这个json字符串:

{
  "$type": "MyAssembly.MyType, MyAssembly",
  "$id": 1,
  "MyValue": 5
}

我可以将它转换成这个json:

{
  "MyValue": 5
}

我已经尝试将原始json加载到JObject中,然后删除所有以$开头的成员,但是在使用数组时发现这个失败,因为它们看起来像这样:

{
  "MyArray": {
    "$type": "System.Collections.List, System",
    "$values": [
      {
        "$type": "MyAssembly.MyType, MyAssembly",
        "MyValue": 5
      }
    ]
  }
}

JSON.NET中是否包含允许进行此类转换的内容?

这是一个显示我的意思的例子

class Program
{
    static void Main(string[] args)
    {
        JsonSerializerSettings withNamehandling = new JsonSerializerSettings()
        {
            TypeNameHandling = TypeNameHandling.All,
            ReferenceLoopHandling = ReferenceLoopHandling.Serialize,
            PreserveReferencesHandling = PreserveReferencesHandling.All,
            Formatting = Formatting.Indented
        };

        var obj = new MyObj();

        //This is the json which my application will be receiving. My application does not know about MyObj or MyType.
        var json = JsonConvert.SerializeObject(obj, withNamehandling);
        Console.WriteLine(json);

        //Deserialize the object without namehandling enabled
        var deserializeObject = JsonConvert.DeserializeObject(json);
        //Serialize again without namehandling enabled
        var json2 = JsonConvert.SerializeObject(deserializeObject, Formatting.Indented);
        //Metadata removed from root node but not children.
        Console.WriteLine(json2);

        Console.ReadLine();
    }
}

class MyObj
{
    public List<MyType> Types { get; set; } = new List<MyType>()
    {
        new MyType()
        {
            Value = 5
        }
    };
}

class MyType
{
    public int Value { get; set; }
}

2 个答案:

答案 0 :(得分:0)

如果我使用http://json2csharp.com/,我会得到以下结构

public class RootObject
{
    public string __invalid_name__$type { get; set; }
    public int __invalid_name__$id { get; set; }
    public int MyValue { get; set; }
}

如果您将模型创建为

,那该怎么办?
public class MyType
{
    public int MyValue { get; set; }
}

然后将其反序列化为该类型MyType

您也可以使用JsonProperty注释,并且不需要特定的属性,如

public class RootObject
{
    [JsonProperty(Required = Required.Default)]
    public string __invalid_name__$type { get; set; }
    [JsonProperty(Required = Required.Default)]
    public int __invalid_name__$id { get; set; }
    public int MyValue { get; set; }
}

答案 1 :(得分:0)

是的,您可以反序列化数据,然后重新序列化。默认情况下,JSON .NET不包含类型名称,因此必须由序列化端设置,以便使用相同的程序集来序列化/反序列化数据,因此在没有实际源程序集的情况下操作该数据时要小心。

无论如何,要对数据进行反序列化,首先要创建一个适合实际数据的模型:

public class RootObject
{
    public List<MyObject> MyArray { get; set; }
}

public class MyObject
{
    public MyType MyValue { get; set; }
}

//I assume this because there's not info about "MyType"
public class MyType : String { }

现在您创建JsonSerializerSettings并将TypeNameHandling设置为None

var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.None };

将数据反序列化到结构中:

var deser = JsonConvert.DeserializeObject<RootObject>(seria, settings);

现在您已经重建了数据并且可以在没有类型处理的情况下对其进行重新序列化,它将删除所有名称空间和类类型:

var cleanJson =  JsonConvert.SerializeObject(deser, settings);

编辑:

如果您不需要重建结构,只需使用已发布的设置并取消/序列化为JObject:

var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.None };
var deser = JsonConvert.DeserializeObject(SourceData, settings);
var clean = JsonConvert.SerializeObject(deser, settings);