将IKVMC生成的对象序列化为JSON

我有一个java库,其中包含我们的后端REST API的所有域模型。 后端API使用Java实现,并使用Jackson将Java对象转换为JSON。

最近,我们需要实现一个新function,并让Windows .NET应用程序与我们的API通信。 但是,由于域模型(契约)都是Java,我们必须将所有Java类转换为C#类,以便我们可以使用Json.NET来序列化/反序列化JSON,但这很快就变得非常耗时。 此外,当Java中的合同发生变化时,我们可能也必须为C#类执行此操作。

我在网上搜索并发现IKVMC可以将jar转换为DLL,所以我试了一下,但是,它导致了一些Json.NET序列化问题。

例如

我有一个看起来像这样的Java对象:

public class ApiToken { private String apiKey; private String apiSecret; public String getApiKey() { return apiKey; } public void setApiKey(String apiKey) { this.apiKey = apiKey; } public String getApiSecret() { return apiSecret; } public void setApiSecret(String apiSecret) { this.apiSecret = apiSecret; } @Override public int hashCode() { return Objects.hashCode(apiKey, apiSecret); } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; ApiToken other = (ApiToken) obj; return Objects.equal(this.apiKey, other.apiKey) && Objects.equal(this.apiSecret, other.apiSecret); } @Override public String toString() { return Objects.toStringHelper(this).add("apiKey", apiKey).add("apiSecret", apiSecret).toString(); } } 

在ikvmc翻译之后 ,它看起来像这样:

 public class ApiToken : Object { [LineNumberTable(11)] [MethodImpl(MethodImplOptions.NoInlining)] public ApiToken(); public virtual string getApiKey(); public virtual void setApiKey(string apiKey); public virtual string getApiSecret(); public virtual void setApiSecret(string apiSecret); [LineNumberTable(35)] public override int hashCode(); [LineNumberTable(new byte[] {159, 182, 100, 98, 99, 98, 110, 98, 103})] [MethodImpl(MethodImplOptions.NoInlining)] public override bool equals(object obj); [LineNumberTable(52)] public override string toString(); } 

当我在C#中创建此对象时,JSON.net不会正确地对此对象进行seralize。 相反,它只生成一个空的JSON {}

我怀疑这是因为ikvmc生成的对象中没有暴露的字段/属性。

有谁知道这是否有解决方法?

非常感谢,非常感谢

更新:这是我序列化对象的方式

  ApiToken apiToken = new ApiToken(); apiToken.setApiKey("test"); apiToken.setApiSecret("secret"); string json = JsonConvert.SerializeObject(apiToken); 

json输出为{}。

我怀疑这是因为ikvmc生成的对象中没有暴露的字段/属性

是。

有谁知道这是否有解决方法?

您可以通过编写自定义ContractResolverValueProvider来完成此操作

 var obj = new ApiToken(); obj.setApiKey("XXX"); obj.setI(666); var settings = new Newtonsoft.Json.JsonSerializerSettings() { ContractResolver = new MyContractResolver() }; var json = JsonConvert.SerializeObject(obj, settings); //json : {"ApiKey":"XXX","I":666} var newobj = JsonConvert.DeserializeObject(json, settings); 

 //Test class public class ApiToken { private String apiKey; public String getApiKey() { return apiKey; } public void setApiKey(String apiKey) { this.apiKey = apiKey; } private int i; public int getI() { return i; } public void setI(int i) { this.i = i; } public string dummy() { return "abcde"; } } 

 public class MyContractResolver : Newtonsoft.Json.Serialization.DefaultContractResolver { protected override IList CreateProperties(Type type, Newtonsoft.Json.MemberSerialization memberSerialization) { //Find methods. setXXX getXXX var properties = type.GetMethods() .Where(m => m.Name.Length > 3) .GroupBy(m => m.Name.Substring(3)) .Where(g => g.Count() == 2 && g.Any(x=>x.Name=="set" + g.Key) && g.Any(x=>x.Name=="get" + g.Key)) .ToList(); //Create a JsonProperty for each set/getXXX pair var ret = properties.Select(prop=> { var jProp = new Newtonsoft.Json.Serialization.JsonProperty(); jProp.PropertyName = prop.Key; jProp.PropertyType = prop.First(m => m.Name.StartsWith("get")).ReturnType; jProp.ValueProvider = new MyValueProvider(prop.ToList()); jProp.Readable = jProp.Writable = true; return jProp; }) .ToList(); return ret; } } public class MyValueProvider : Newtonsoft.Json.Serialization.IValueProvider { List _MethodInfos = null; public MyValueProvider(List methodInfos) { _MethodInfos = methodInfos; } public object GetValue(object target) { return _MethodInfos.First(m => m.Name.StartsWith("get")).Invoke(target, null); } public void SetValue(object target, object value) { _MethodInfos.First(m => m.Name.StartsWith("set")).Invoke(target, new object[] { value }); } }