将IKVMC生成的对象序列化为JSON [英] Serializing a IKVMC generated object to JSON

查看:138
本文介绍了将IKVMC生成的对象序列化为JSON的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a java library that contains all the domain models for our backend REST API. The backend API is implemented in Java and translate Java objects to JSON using Jackson.

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

Recently we need to implement a new feature and have a Windows .NET application talk to our API. However, since the domain model (contract) is all in Java, we had to translate all the Java classes to C# classes so that we can use Json.NET to serialize/deserialize JSON, but this quickly became time-consuming. In addition, whenver there is contract change in Java we likely have to do this for C# classes also.

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

I searched online and found out IKVMC can translate a jar to a DLL, so I tried it out, however, it's causing some Json.NET serialization problems.

例如

我有一个如下所示的Java对象:

I have a Java object that looks like this:

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翻译后 ,它看起来像这样:

AFTER translation by ikvmc, it looks like this:

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会 NOT 正确地封闭此对象。相反,它只是产生一个空的JSON {}

when I create this object in C#, JSON.net does NOT seralize this object correctly. Instead, it just produces an empty JSON {}

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

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?

非常感谢和非常感谢

更新:
这是我如何序列化对象

Update: This is how I'm serializing the object

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

json输出为{}。

The json output is {}.

推荐答案


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

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?

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

You can do it by writing a custom ContractResolver and ValueProvider as below

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 });
    }
}

这篇关于将IKVMC生成的对象序列化为JSON的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆