Подтвердить что ты не робот

Как включить тип объекта в Json для веб-службы asmx с помощью Gson

Как сохранить тип объекта в 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, когда я пытаюсь выполнить такой шаблон

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

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


Обновление:

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

4b9b3361

Ответ 1

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

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

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

EDIT: Фактически, вы также можете увидеть этот другой ответ fooobar.com/questions/436204/..., в котором рассказывается о том, как заставить 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 content with the page method 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 content with the page method return.
                        $("#PushResult").text(msg.d);
                    }
                });
            });
        });  
    </script>
</asp:Content>

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

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

Ответ 2

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

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