gpt4 book ai didi

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

转载 作者:太空宇宙 更新时间:2023-11-04 07:03:57 25 4
gpt4 key购买 nike

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

最近我们需要实现一项新功能,并让 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 正确序列化此对象。相反,它只是生成一个空的 JSON{}

我怀疑这是因为 ikvmc 生成的对象中没有公开任何字段/属性。

有人知道是否有解决方法吗?

非常感谢,非常感谢

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

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

json 输出为 {}。

最佳答案

I suspect this is because there are no fields/properties exposed in the object that is generated by ikvmc

是的。

Does anyone know if there's a workaround for this?

您可以通过编写自定义 ContractResolverValueProvider 来实现,如下所示

var obj = new ApiToken();
obj.setApiKey("X-X-X");
obj.setI(666);

var settings = new Newtonsoft.Json.JsonSerializerSettings() {
ContractResolver = new MyContractResolver()
};

var json = JsonConvert.SerializeObject(obj, settings);
//json : {"ApiKey":"X-X-X","I":666}
var newobj = JsonConvert.DeserializeObject<ApiToken>(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<Newtonsoft.Json.Serialization.JsonProperty> 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<MethodInfo> _MethodInfos = null;
public MyValueProvider(List<MethodInfo> 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 });
}
}

关于c# - 将 IKVMC 生成的对象序列化为 JSON,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21686159/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com