将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生成的对象中没有暴露的字段/属性
是。
有谁知道这是否有解决方法?
您可以通过编写自定义ContractResolver和ValueProvider来完成此操作
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 }); } }