通过JSON将继承对象传递给WCF服务

4 投票
2 回答
2000 浏览
提问于 2025-04-16 12:59

我有两个类,下面列出了它们。

public Class Vehicle
{
   int wheels { get ; set}
}

public Class Car:Vehicle
{
   int topspeed { get; set ;}
}

//This is the container class

public Class Message
{
   string ConatinerName { get; set;}
   Vehicle Container;
}

我定义了一个服务合同,样子如下。这个网络服务有两个接口,一个是SOAP,另一个是Json。

//this function gets a message object, looks into the container
public Message GetMessage(Message Input)
{
   Car mycar = (Car)Message.Container;
   mycar.topspeed = 200;
   Message retMessage = new Message();
   retMessage.ContainerName ="Adjusted Car Speed";
   retMessage.Container = mycar;
   return retMessage;
}

当我运行WCF网络服务时,Visual Studio自带的测试客户端能够用一个消息对象调用这个服务,并且提供了选项,可以在消息容器中传入一个汽车对象或者一个车辆对象。VS客户端根据传入的原始数据使用SOAP接口。

为了测试服务的Json接口,我使用了一个用Python写的简单客户端,它通过Json数据格式调用上面的网络服务的GetMessage()方法。我传入了一个Car对象,但当服务实际接收到数据时,

这个网络服务方法获取到的数据,容器里面只包含了车辆对象。我检查了web方法接收到的请求上下文,显示接收到了正确的Json字符串(和发送的一样),但.NET不知怎么的却把Car类的属性去掉了,只传入了Vehicle属性。所以在GetMessage()里面尝试将其转换为汽车时,就抛出了一个异常,提示你试图将一个车辆转换为汽车,这是不合法的转换。

现在我明白了,Message里面的ContainerVehicle类型的,但对于SOAP接口,我可以传入汽车对象和车辆对象,而对于Json接口,只能通过Message容器传入一个车辆对象。

我的问题是,如何让.NET运行时识别我想传入的是Car而不是Vehicle呢?

我的Json客户端代码如下。

import urllib2, urllib, json

def get_json(url):
                f = urllib2.urlopen(url)
                resp = f.read()
                f.close()
                return json.loads(resp)

def post(url, data):
                headers = {'Content-Type': 'application/json'}
                request = urllib2.Request(url, data, headers)
                f = urllib2.urlopen(request)
                response = f.read()
                f.close()
                return response

geturl = 'http://localhost:24573/Service1.svc/json/GetMessage'
sendurl = 'http://localhost:24573/Service1.svc/json/SendMessage'

msg = get_json(geturl)
print 'Got', msg
print 'Sending...'
retval = post(sendurl, json.dumps(msg))
print 'POST RESPONSE', retval

2 个回答

0

在车辆类中添加这个属性

[KnownType(typeof("Car"))]

4

我在用Python调用WCF服务时遇到了类似的问题,使用JSON格式的数据。让我惊讶的是,解决这个问题的方法是确保在发送请求时,__type这个键放在最前面。

举个例子,使用json.dumps(data, sort_keys=True)会返回类似这样的结果。WCF服务不喜欢这个,因为__type没有放在Container的最前面。所以,我的建议是确保__type是第一个。还有,我挺惊讶sort_keys这个选项并不是递归的。

错误示例:

{"Container": {"Model": "El Camino", "TopSpeed": 150, "Wheels": 0, "__type": "Car:#WcfService1"},"WrapperName": "Car Wrapper"}

正确示例:

{"Container": {"__type": "Car:#WcfService1", "Model": "El Camino", "TopSpeed": 150, "Wheels": 0},"WrapperName": "Car Wrapper"}

这是一个简单的Python测试客户端。

import urllib2, urllib, json

def get_json(url):
    f = urllib2.urlopen(url)
    resp = f.read()
    f.close()
    return json.loads(resp)


def post(url, data):
    headers = {'Content-Type': 'application/json'}
    request = urllib2.Request(url, data, headers)
    f = urllib2.urlopen(request)
    response = f.read()
    f.close()
    return response

geturl = 'http://localhost:24573/Service1.svc/json/GetMessage'
sendurl = 'http://localhost:24573/Service1.svc/json/SendMessage'

msg = get_json(geturl)
print 'Got', msg
print 'Sending...'
retval = post(sendurl, json.dumps(msg))
print 'POST RESPONSE', retval

撰写回答