我想做的事情如下:
MyObject myObj = GetMyObj(); // Create and fill a new object
MyObject newObj = myObj.Clone();
Run Code Online (Sandbox Code Playgroud)
然后更改未在原始对象中反映的新对象.
我不经常需要这个功能,所以当有必要的时候,我已经使用了创建一个新对象然后单独复制每个属性,但它总是让我觉得有更好或更优雅的处理方式情况.
如何克隆或深度复制对象,以便可以修改克隆对象而不会在原始对象中反映任何更改?
我试图扩展这里给出的JSON.net示例 http://james.newtonking.com/projects/json/help/CustomCreationConverter.html
我有另一个派生自基类/接口的子类
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Employee : Person
{
public string Department { get; set; }
public string JobTitle { get; set; }
}
public class Artist : Person
{
public string Skill { get; set; }
}
List<Person> people = new List<Person>
{
new Employee(),
new Employee(),
new Artist(),
};
Run Code Online (Sandbox Code Playgroud)
如何将Json反序列化回List <Person>
[
{
"Department": "Department1",
"JobTitle": "JobTitle1",
"FirstName": "FirstName1", …Run Code Online (Sandbox Code Playgroud) 我有一个类定义,其中包含一个返回接口的属性.
public class Foo
{
public int Number { get; set; }
public ISomething Thing { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
尝试使用Json.NET序列化Foo类给出了一条错误消息,例如"无法创建类型为'ISomething'的实例.ISomething可能是一个接口或抽象类."
是否有Json.NET属性或转换器可以让我指定Something在反序列化期间使用的具体类?
我想通过json.net序列化这段代码:
public interface ITestInterface
{
string Guid {get;set;}
}
public class TestClassThatImplementsTestInterface1
{
public string Guid { get;set; }
}
public class TestClassThatImplementsTestInterface2
{
public string Guid { get;set; }
}
public class ClassToSerializeViaJson
{
public ClassToSerializeViaJson()
{
this.CollectionToSerialize = new List<ITestInterface>();
this.CollectionToSerialize.add( new TestClassThatImplementsTestInterface2() );
this.CollectionToSerialize.add( new TestClassThatImplementsTestInterface2() );
}
List<ITestInterface> CollectionToSerialize { get;set; }
}
Run Code Online (Sandbox Code Playgroud)
我想用json.net序列化/反序列化ClassToSerializeViaJson.序列化工作正常,但反序列化给了我这个错误:
Newtonsoft.Json.JsonSerializationException:无法创建ITestInterface类型的实例.Type是接口或抽象类,无法实例化.
那么我该如何反序列化List<ITestInterface>集合呢?
我将在前言中说我知道问题是什么,我只是不知道如何解决它.我正在与.NET SOA数据层进行通信,该数据层将数据作为JSON返回.一种这样的方法返回一个在其中包含多个集合的对象.该对象基本上如下所示:
{
"Name":"foo",
"widgetCollection":[{"name","foo"}, {"name","foo"},],
"cogCollection": [{"name","foo"}, {"childCogs",<<new collection>>},],
}
Run Code Online (Sandbox Code Playgroud)
我代表这个对象的类看起来像这样:
public class SuperWidget : IWidget
{
public string Name { get; set; }
public ICollection<IWidget> WidgetCollection { get; set; }
public ICollection<ICog> CogCollection { get; set; }
public SuperWidget()
{
}
[JsonConstructor]
public SuperWidget(IEnumerable<Widget> widgets, IEnumerable<Cog> cogs)
{
WidgetCollection = new Collection<IWidget>();
CogCollection = new Collection<ICog>();
foreach (var w in widgets)
{
WidgetCollection.Add(w);
}
foreach (var c in cogs)
{
CogCollection.Add(c);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这个构造函数工作正常,直到cogCollection添加了一个子集合,现在我收到了上面的错误.具体的cog类看起来像这样:
[Serializable]
public class …Run Code Online (Sandbox Code Playgroud) 我有以下问题,我无法解决:
我有不同的类,它们都实现了一个名为的接口IProtocol.的命名,现在,SimpleProtocol,ParallelProtocol.我想坚持这些对象,所以我使用JSON.NET,一切正常.除非我试图反序列化它们,当我知道它们应该是什么类型时,它会完美地工作,例如:
SimpleProtocol p = JsonConvert.DeserializeObject<SimpleProtocol>(myJsonData);
Run Code Online (Sandbox Code Playgroud)
但是,我现在处于需要加载JSON数据并IProtocol返回的情况,但可以理解的是,JSON不允许这样做; 例如,这样的事情并没有工作:
IProtocol p1 = JsonConvert.DeserializeObject<IProtocol>(myJsonData); // does not work
IProtocol p2 = (IProtocol)JsonConvert.DeserializeObject(myJsonData); // also, does not work
Run Code Online (Sandbox Code Playgroud)
所以,查找API我发现了这个方法签名:
public static Object DeserializeObject(
string value,
Type type
)
Run Code Online (Sandbox Code Playgroud)
看起来就像我需要的东西,所以通过将字符串中的类型持久化并检索它来尝试:
// test
Type protocolType = Type.GetType("MyApp.Protocols.SimpleProtocol");
IProtocol p1 = JsonConvert.DeserializeObject(myJsonData, protocolType);
Run Code Online (Sandbox Code Playgroud)
我得到一个错误,这是不可能投下Newtonsoft.Json.Linq.JObject到IProtocol.这很奇怪,我不知道如何解决这个问题.
在泛型方法中传递Type对象是不可能的,所以我基本上被困在这里.有没有办法解决这个问题,最好不要使用反射?在我看来,这是一个完全正常的用例.
我能做什么,但对我来说似乎有点"脏",是创建一个简单的包装类,它包含一个IProtocol实例并序列化/反序列化?
在这个链接上,在备注部分提到了" TypeNameHandling".在什么情况下,如果使用序列化/反序列化来自外部源的JSON会有害SerializationBinder?一个工作的例子将不胜感激.
我正在将有效的 JSON 对象传递到 .net core 3 Web api 应用程序上的控制器。这样做,我收到错误:
System.NotSupportedException:不支持接口类型的反序列化。输入“OrderTranslationContracts.OrderContracts+IImportOrderLineModel”
所以我查看了我的代码,并得到了以下接口的具体实现。这是我认为引发错误的行:
public List<OrderContracts.IImportOrderLineModel> Lines { get; set; }
Run Code Online (Sandbox Code Playgroud)
以下是我传递到控制器的 JSON 部分:
"lines": [
{
"orderNumber": "LV21131327",
"lineNumber": 1,
"itemId": "3083US",
"customerItemId": "3083US",
"quantity": 3,
"price": 0.00,
"quantityBackOrdered": null,
"comments": "",
"pickLocation": "",
"orderFilled": "O",
"hostUom": null,
"type": null
}
Run Code Online (Sandbox Code Playgroud)
所以我知道 JSON 是有效的。这是控制器的签名:
[HttpPost]
public async Task<List<ImportOrderModel>> Post([FromBody] List<ImportOrderModel> orders)
{
var response = await _validateOrder.ValidateAllOrdersAsync(orders, null);
return response;
}
Run Code Online (Sandbox Code Playgroud)
我什至没有闯入这段代码,因为我假设 JSON 反序列化器在尝试转换它时抛出错误。那么我该如何克服这个错误呢?我受到接口的具体实现的约束,因此我无法更改接口,如果可能的话,我需要使用我这里拥有的接口。如果这是不可能的,是否有任何“解决方法”?
注意:我正在使用 Microsoft 的新产品
System.Text.Json,Json.NET因此请确保答案相应地解决了这个问题。
考虑这些简单的 POCO:
interface Vehicle {}
class Car : Vehicle {
string make { get; set; }
int numberOfDoors { get; set; }
}
class Bicycle : Vehicle {
int frontGears { get; set; }
int backGears { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
汽车可以像这样用 JSON 表示......
{
"make": "Smart",
"numberOfDoors": 2
}
Run Code Online (Sandbox Code Playgroud)
自行车可以这样表示......
{
"frontGears": 3,
"backGears": 6
}
Run Code Online (Sandbox Code Playgroud)
很直接。现在考虑这个 JSON。
[
{
"Car": {
"make": "Smart",
"numberOfDoors": 2
}
},
{
"Car": {
"make": …Run Code Online (Sandbox Code Playgroud) 我在反序列化我的对象时遇到问题。它包含以下属性:
public List<IShape> Shapes { get; set; };
Run Code Online (Sandbox Code Playgroud)
JSON.NET 反序列化器总是告诉我,不可能实例化接口。
我有几个实现 IShape 接口的类,例如Polyline -> IPolyline -> IShape。我已经尝试了两种解决方案:
但我得到了同样的异常,即 IShape 无法实例化,被抛出。
TypeNameHandling.Auto我用,序列化对象TypeNameHandling.All也没有帮助,即使我使用上面链接的帖子中提到的转换器也是如此。
有谁知道这个问题的解决方案?如果需要一些代码,我很乐意发布它。
以下是生成的 JSON 示例。
"$type": "SketchModel.Layer, SketchModel",
"Id": 57865477,
"Shapes": {
"$type": "System.Collections.Generic.List`1[[SketchModel.Shapes.AbstractShapes.IShape, SketchModel]], mscorlib",
"$values": [
{
"$type": "SketchModel.Shapes.Polyline, SketchModel",
Run Code Online (Sandbox Code Playgroud)
该行负责解决这个问题:
"System.Collections.Generic.List`1[[SketchModel.Shapes.AbstractShapes.IShape, SketchModel]], mscorlib"
Run Code Online (Sandbox Code Playgroud)
它根本不知道如何实例化 IShape。如果我创建一个自定义转换器并让它为每个 IShape 返回一条折线,它可以工作,但不会创建任何其他形状(例如椭圆)。
在
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)自定义转换器中重写的方法中,如果我让我打印 objectType 的完整类型名称,它始终是 IShape,而不是其他任何内容......