Как включить тип объекта в Json для веб-службы asmx с помощью Gson - PullRequest
12 голосов
/ 08 февраля 2012

Как сохранить тип объекта в строке json при отправке данных в веб-службу asmx в .net 2.0?

, например:

class A{
 string name;
}

class B : A {
 string address;
}

и веб-метод:

[WebMethod]
public void PushJson(A obj){
  B b = (B) obj;
}

Теперь в приведенном выше примере сценария, скажем, я отправляю {"obj":{"name":"waqas","address":"sweden"}}, тогда как я могу заставить мою строку json действовать как тип класса B, такчто он может быть принят веб-методом как объект класса A и затем проанализирован обратно в объект класса B?Короче говоря, как сохранить полиморфизм в json?

Я заметил, что компилятор выбрасывает меня System.InvalidCastException, когда я пытаюсь выполнить такой шаблон

PS Я заметил, что.net добавляет __ type для сложных объектов при сериализации в json.Возможно ли, что мы можем включить этот ключ, чтобы помочь .net автоматически анализировать строку json с правильным типом класса?

будет полезна любая помощь / предложение.


Обновление:

Если мы тщательно соблюдаем wsdl веб-службы asmx, то объекты, чьи классы наследуют родительские классы, содержат что-то вроде <s:extension base="tns:ParentClassName">.Я думаю, что эта часть расширения - это то, что мне может понадобиться преобразовать в Json.Есть идеи по этому поводу?

Ответы [ 2 ]

6 голосов
/ 13 августа 2012

Вы упоминаете GSON в своем названии, но я не уверен, где он играет в эту картину.Так что я могу ошибиться.Однако, если вы просто спрашиваете, как заставить .NET десериализовать ваш JSON, вы можете использовать параметр __type.Он должен прийти первым.

{"obj":{"__type":"B","name":"waqas","address":"sweden"}}

Я смог заставить его работать в тестовом проекте, но, как я уже сказал, GSON не задействован.

РЕДАКТИРОВАТЬ: На самом деле, вы также можете захотеть увидеть этот другой ответ https://stackoverflow.com/a/10805715/1539015, в котором говорится о том, как заставить GSON включить этот параметр __type.

EDIT2: Я создал новый .NETВеб-сайт.Добавлен файл классов с вашими классами A и B (изменен, чтобы сделать их общедоступными):

public class A
{
    public string name;
}

public class B : A
{
    public string address;
}

Затем я добавил веб-сервис, чтобы использовать WebMethod, который вы указали в вопросе.Я также включил метод GetJson.Вот код:

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService]
public class WebService : System.Web.Services.WebService {

    public WebService () {
    }

    [ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)]
    [WebMethod]
    public B GetJson()
    {
        return new B() { address = "addr", name = "nm" };
    }

    [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
    [WebMethod]
    public string PushJson(A obj)
    {
        B b = (B)obj;
        return b.address;
    }
}

Затем я отредактировал страницу по умолчанию для вызова веб-метода с помощью jQuery:

<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
    <p>
        <div id="GetResult">Click here for the result of getting json.</div>    
        <div id="PushResult">Click here for the result of pushing json.</div>    
    </p>
    <script type="text/javascript">
        $(document).ready(function () {
            // Add the page method call as an onclick handler for the div.
            $("#GetResult").click(function () {
                $.ajax({
                    type: "GET",
                    url: "WebService.asmx/GetJson",
                    contentType: "application/json; charset=utf-8",
                    success: function (msg) {
                        // Replace the div's content with the page method's return.
                        $("#GetResult").text(msg.d.name);
                    }
                });
            });
            $("#PushResult").click(function () {
                $.ajax({
                    type: "POST",
                    url: "WebService.asmx/PushJson",
                    data: '{"obj":{"__type":"B","name":"waqas","address":"sweden"}}',
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    success: function (msg) {
                        // Replace the div's content with the page method's return.
                        $("#PushResult").text(msg.d);
                    }
                });
            });
        });  
    </script>
</asp:Content>

Если вы поместите точку останова в метод веб-службы PushJson, вывидно, что созданный объект имел тип B, и он также показывает, что его можно привести к типу B. и использовать.

Здесь нет GSON, но я считаю, что другой пост, на который я ссылался, должен показать, какчтобы получить GSON для генерации параметра __type.

3 голосов
/ 15 февраля 2012

Я не уверен, что это на 100% актуально, так как вы упомянули в комментариях, что вы не можете изменить WebService, но, используя System.Web.Script.Serialization JavaScriptSerializer, вы можете десериализовать любой из типов:

JavaScriptSerializer serializer = new JavaScriptSerializer();
A a = serializer.Deserialize<A>(jsonStr);
B b = serializer.Deserialize<B>(jsonStr);
...