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

C# 将IKVMC生成的对象序列化为JSON,c#,java,json,serialization,ikvm,C#,Java,Json,Serialization,Ikvm,我有一个java库,其中包含我们后端RESTAPI的所有域模型。后端API是用Java实现的,并使用Jackson将Java对象转换为JSON 最近,我们需要实现一个新功能,并让一个Windows.NET应用程序与我们的API对话。 然而,由于域模型(契约)都在Java中,我们必须将所有Java类转换为C#类,以便使用Json.NET对Json进行序列化/反序列化,但这很快就变得非常耗时。此外,当Java中存在契约变更时,我们可能也必须对C#类这样做 我在网上搜索发现,IKVMC可以将jar转换

我有一个java库,其中包含我们后端RESTAPI的所有域模型。后端API是用Java实现的,并使用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();
    }
}
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();
  }
经ikvmc翻译后,如下所示:

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();
    }
}
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输出为{}

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

有人知道有没有解决办法吗

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


公共类MyContractResolver:Newtonsoft.Json.Serialization.DefaultContractResolver
{
受保护的重写IList CreateProperties(类型为Newtonsoft.Json.MemberSerialization MemberSerialization)
{
//查找方法。setXXX getXXX
var properties=type.GetMethods()
.其中(m=>m.Name.Length>3)
.GroupBy(m=>m.Name.Substring(3))
。其中(g=>g.Count()==2&&g.Any(x=>x.Name==“set”+g.Key)&&g.Any(x=>x.Name==“get”+g.Key))
.ToList();
//为每个set/getXXX对创建一个JsonProperty
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=新的MyValueProvider(prop.ToList());
jProp.Readable=jProp.writeable=true;
返回jProp;
})
.ToList();
返回ret;
}
}
公共类MyValueProvider:Newtonsoft.Json.Serialization.IValueProvider
{
列表_MethodInfos=null;
公共MyValueProvider(列表方法信息)
{
_MethodInfos=MethodInfos;
}
公共对象GetValue(对象目标)
{
返回_MethodInfos.First(m=>m.Name.StartsWith(“get”)).Invoke(target,null);
}
public void SetValue(对象目标、对象值)
{
_MethodInfos.First(m=>m.Name.StartsWith(“set”)).Invoke(目标,新对象[]{value});
}
}

您如何使用JSON.net序列化此文件?你能告诉我你在哪里调用JSON.net吗?我已经更新了这个问题,谢谢
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 });
    }
}