sourcecode

JSON 개체에서 __type 속성을 직렬화하지 않는 방법

codebag 2023. 3. 4. 14:54
반응형

JSON 개체에서 __type 속성을 직렬화하지 않는 방법

WebMethodScriptService는 JSON 오브젝트에 포함되어 있습니다.d 그 이상 않는다.__typej를 사용하여 수동 Query를 사용하여 수동 처리를 하기 때문에 클라이언트에 제공되어야 하는 속성입니다.

가능합니까?

webmethod public은 .__type:ClassName★★★★★★ 。

컨스트럭터 「Default Constructor」를 할 수 .protected internal ClassName() { }

반환할 유형이 별도의 DLL이기 때문에 John의 솔루션은 작동하지 않았습니다.해당 DLL을 완전히 제어할 수 있지만 생성자가 내부인 경우 반환 유형을 구성할 수 없습니다.

반납 타입이 도서관에 있는 퍼블릭 타입이 원인인지 궁금했습니다.저는 Ajax를 많이 하고 있는데 이 타입을 본 적이 없습니다.

간단한 테스트:

  • App_Code를 사용합니다. 직 still still still still still still still still still still 。__type시리얼화되었습니다.

  • JM에 따라 보호된 내부 컨스트럭터를 적용했습니다.이것은 효과가 있었다(그래서 그는 표를 얻었다).

하게 이해가 안 돼__type"이것들"은 다음과 같습니다.

[WebMethod]
public static WebMethodReturn<IEnumerable<FleetObserverLiteAddOns.VehicleAddOnAccountStatus>> GetAccountCredits()

그러나 해결책은 반환 유형을 DLL에 그대로 두고 WebMethod 반환 유형을 개체로 변경하는 것이었습니다.

[WebMethod]
public static object ApplyCredits(int addonid, int[] vehicleIds) 

대신

[WebMethod]
public static WebMethodReturn ApplyCredits(int addonid, int[] vehicleIds)

이 제안들 중 몇 가지를 와 함께 시도하고 있습니다.NET 4 WCF 서비스가 작동하지 않는 것 같습니다.JSON 응답에는 __type이 포함되어 있습니다.

유형 힌트를 제거하는 가장 쉬운 방법은 엔드포인트 동작을 enableWebScript에서 webHttp로 변경하는 것입니다.

    <behavior name="MapData.MapDataServiceAspNetAjaxBehavior">
      <webHttp />
    </behavior>

ASP를 사용하는 경우 기본 enableWebScript 동작이 필요합니다.NET AJAX 클라이언트는 JavaScript 또는 jQuery를 사용하여 JSON을 조작하는 경우 webHttp 동작을 선택하는 것이 좋습니다.

ServiceStack을 사용하는 경우.텍스트 JSON Serializer는 다음 작업만 하면 됩니다.

JsConfig.ExcludeTypeInfo = true;

이 기능은 v2.28에서 자동으로 추가되었지만 위의 코드로 인해 시리얼라이제이션에서 제외됩니다.이 동작은 다음 방법으로도 변경할 수도 있습니다.Type 라이선스:

JsConfig<Type>.ExcludeTypeInfo = true;

의문의 '_형'의 근본 원인을 좁힌 것 같아!

다음은 문제를 재현할 수 있는 예입니다.

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
[System.Web.Script.Services.ScriptService]
public class Test : System.Web.Services.WebService
{
    public class Cat
    {
        public String HairType { get; set; }
        public int MeowVolume { get; set; }
        public String Name { get; set; }
    }

    [WebMethod]
    public String MyMethodA(Cat cat)
    {
        return "return value does not matter";
    }

    [WebMethod]
    public Cat MyMethodB(String someParam)
    {
        return new Cat() { HairType = "Short", MeowVolume = 13, Name = "Felix the Cat" };
    }
}

여기가 포인트!

단순히 MyMethodA()가 이 .asmx 파일에 존재하고 Cat 클래스를 파라미터로 사용하기 때문입니다.__type은 다른 메서드를 호출하고 반환된 JSON에 추가됩니다.MyMethodB().

방법은 다르지만!!

제 이론은 다음과 같습니다.

  1. 이와 같은 웹 서비스를 작성할 때 [WebMethod] 및 [ScriptService]와 같은 올바른 속성을 사용했기 때문에 Microsoft의 코드가 자동으로 JSON 직렬화/비직렬화 동작을 연결합니다.
  2. 이 자동 매직 Microsoft 코드가 실행되면 Cat 클래스를 매개 변수로 받아들이는 메서드가 검색됩니다.
  3. 그러니까...아...알겠습니다...JSON에서 Cat 오브젝트를 받을 예정이니까...현재 웹 서비스 클래스의 메서드에서 Cat 개체를 JSON으로 반환할 경우...나중에 C#으로 역직렬화 할 때 식별하기 쉽도록 __type 속성을 부여합니다.
  4. 냐하하하하...

중요한 테이크아웃 노트

생성된 JSON에 __type 속성이 표시되지 않도록 하려면 해당 클래스(내 경우 Cat)를 웹 서비스의 WebMethod에 대한 파라미터로 사용하지 마십시오.따라서 위의 코드에서는 MyMethodA()를 변경하여 Cat 파라미터를 삭제합니다.이로 인해 __type 속성이 생성되지 않습니다.

JavaScriptTypeResolver에 null을 전달하면 __type은 직렬화되지 않습니다.

JavaScriptSerializer serializer = new JavaScriptSerializer(null);
string json = serializer.Serialize(foo);

제 2센트입니다만, 다른 사람들이 언급했듯이, "_타입" 재산을 막는 방법은 두 가지가 있는 것 같습니다.

a) 파라미터가 없는 생성자를 보호한다.

b) 클래스를 Web 메서드에 파라미터로 전달하는 것을 피한다.

클래스를 매개 변수로 전달할 필요가 없는 경우 생성자를 "protected internal"로 만들 수 있습니다.빈 개체를 만들어야 할 경우 공장 메서드 또는 더미 매개 변수를 사용하여 다른 생성자를 추가하십시오.

단, 클래스를 파라미터로서 Web 메서드에 전달할 필요가 있는 경우 파라미터가 없는 컨스트럭터가 보호되어 있으면 동작하지 않습니다(아마도 전달된json 데이터를 클래스에 역직렬화할 수 없기 때문에 ajax 호출이 실패합니다).

이것은 저의 문제였기 때문에 (a)와 (b)의 조합을 사용해야 했습니다.파라미터 없는 컨스트럭터를 보호하고 웹 메서드에 대한 파라미터 전용으로 사용되는 더미 파생 클래스를 만듭니다.예:

public class MyClass
{
    protected internal MyClass() { }
    public MyClass(Object someParameter) { }
    ...
}

// Use this class when we need to pass a JSON object into a web method
public class MyClassForParams : MyClass
{
    public MyClassForParams() : base() { }
}

MyClass에서 사용해야 하는 웹 메서드는 대신 MyClassForParams를 사용합니다.

[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public MyClass DoSomething(MyClassForParams someObject)
{
    // Do something with someObject
    ...
    // Maybe return a MyClass object
    ...
}

이것이 좋은 해결책이라고 확신할 수는 없지만 제이슨.net 라이브러리를 사용하는 경우 [JsonIgnore]속성을 추가하여 일부 속성을 무시할 수 있습니다.

웹 서비스와 대부분의 WCF에서 놀라울 정도로 잘 작동하는 DataContract 클래스의 내부 또는 보호 대상 내부 컨스트럭터에 대한 John Morrison의 조언과 더불어 web.config 파일을 추가로 변경해야 할 수도 있습니다.대신<enableWebScript/>요소 사용<webHttp/>endpointBehaviors에 대해 예를 들어 다음과 같습니다.

<endpointBehaviors>
  <behavior name="MyServiceEndpoint">
    <webHttp/>
  </behavior>
</endpointBehaviors>

[서버 가능] 속성을 사용하지 마십시오.

다음은 그것을 해야 한다.

Java 스크립트 서버 = 새 Java 스크립트 서버 = 서버를 ser 서버에 연결합니다.직렬화( 객체 클래스)

스레드에게 조금 늦었지만 여기 갑니다.

Json 문자열에 추가될 때 동일한 문제가 발생했습니다.T>우리는 T의 배열이 있는 다른 재산을 추가했습니다.

전에.

[DataMember]
public List<Person> People { get; set; }

끝나고.

public List<Person> People { get; set; }

[DataMember(Name = "People")]
public Person[] Persons {
    get {
        return People.ToArray();
    }
    private set { }
}

이상적인 해결책은 아니지만, 그것은 속임수이다.

그것을 회피하는 방법은 다음과 같다.

    [WebMethod]
    [ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)]
    public void Status()
    {
        MyObject myObject = new MyObject(); // Your class here
        var json = Newtonsoft.Json.JsonConvert.SerializeObject(myObject);

        HttpContext.Current.Response.Write(json);
    }

이거면 해결될 거야.

시스템의 JavaScriptSerializer의 개인 SerializeValue 메서드.WebExtensions.dll, __type이 해결 가능한 경우 내부 딕셔너리에 추가됩니다.

리플렉터에서:

private void SerializeValue(object o, StringBuilder sb, int depth, Hashtable objectsInUse)
{
    if (++depth > this._recursionLimit)
    {
        throw new ArgumentException(AtlasWeb.JSON_DepthLimitExceeded);
    }
    JavaScriptConverter converter = null;
    if ((o != null) && this.ConverterExistsForType(o.GetType(), out converter))
    {
        IDictionary<string, object> dictionary = converter.Serialize(o, this);
        if (this.TypeResolver != null)
        {
            string str = this.TypeResolver.ResolveTypeId(o.GetType());
            if (str != null)
            {
                dictionary["__type"] = str;
            }
        }
        sb.Append(this.Serialize(dictionary));
    }
    else
    {
        this.SerializeValueInternal(o, sb, depth, objectsInUse);
    }
}

유형을 판별할 수 없는 경우 직렬화는 계속 진행되지만 유형은 무시됩니다.좋은 소식은 어나니머스 타입이 getType()을 상속하고 반환된 이름은 컴파일러에 의해 동적으로 생성되므로 TypeResolver는 ResolveTypeId의 늘을 반환하고 "_type" 속성은 무시된다는 것입니다.

만약을 위해 내부 컨스트럭터에게 John Morrison의 조언을 들었지만, 이 방법만으로 JSON 응답에 __type 속성을 얻을 수 있었습니다.

//Given the following class
[XmlType("T")]
public class Foo
{
    internal Foo()
    {

    }

    [XmlAttribute("p")]
    public uint Bar
    {
        get;
        set;
    }
}

[WebService(Namespace = "http://me.com/10/8")]
[System.ComponentModel.ToolboxItem(false)]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService]
public class MyService : System.Web.Services.WebService
{

    //Return Anonymous Type to omit the __type property from JSON serialization
    [WebMethod(EnableSession = true)]
    [System.Web.Script.Services.ScriptMethod(UseHttpGet = false, ResponseFormat = ResponseFormat.Json, XmlSerializeString = false)]
    public object GetFoo(int pageId)
    {
        //Kludge, returning an anonymois type using link, prevents returning the _type attribute.
        List<Foo> foos = new List<Foo>();
        rtnFoos.Add( new Foo(){
            Bar=99
        }};

        var rtn = from g in foos.AsEnumerable()
                   select g;

        return rtn;
    }
}

주의: JSON을 더욱 압축하기 위해 직렬화된 유형에서 XML 직렬화 특성을 읽는 상속된 JSON 유형 변환기를 사용하고 있습니다.Code Journal 덕분에요.마법처럼 작동한다.

@의 @sean 사용 JavaScriptSerializer.

JavaScriptSerializer를 의 JavaScriptSerializer를 ResponseFormat = WebMessageFormat.Json은 이중 결과 이 "JSON"일 그 가 이루어집니다.string, bweteen 큰따옴표 bweteen 큰따옴표가 .

이를 회피하려면 이 훌륭한 답변의 솔루션을 사용하여 콘텐츠유형을 JSON(덮어쓰기)으로 정의하고 이 바이너리 결과를 스트리밍합니다.JavaScriptSerializer.

상기 답변의 코드샘플:

public Stream GetCurrentCart()
{
    //Code ommited
    var j = new { Content = response.Content, Display=response.Display,
                  SubTotal=response.SubTotal};
    var s = new JavaScriptSerializer();
    string jsonClient = s.Serialize(j);
    WebOperationContext.Current.OutgoingResponse.ContentType =
        "application/json; charset=utf-8";
    return new MemoryStream(Encoding.UTF8.GetBytes(jsonClient));
}

JavaScriptSerializer에 있습니다.System.Web.Script.SerializationSystem.Web.Extensions.dll디폴트로는 참조되지 않습니다.

var settings = new DataContractJsonSerializerSettings();
settings.EmitTypeInformation = EmitTypeInformation.Never;
DataContractJsonSerializer serializerInput = new DataContractJsonSerializer(typeof(Person), settings);
var ms = new MemoryStream();
serializerInput.WriteObject(ms, personObj);
string newRequest = Encoding.UTF8.GetString(ms.ToArray());

응답을 보내기 위해 사용자 고유의 반환 유형을 작성할 수 있습니다.또한 응답 use 객체를 반환 유형으로 전송하는 동안 .type 속성은 무시됩니다.

이것은 약간 해킹이지만, 이것은 나에게 효과가 있었다(C# 사용).

s = (JSON string with "__type":"clsname", attributes)
string match = "\"__type\":\"([^\\\"]|\\.)*\",";
RegEx regex = new Regex(match, RegexOptions.Singleline);
string cleaned = regex.Replace(s, "");

에서 합니다.[DataContract] ★★★★★★★★★★★★★★★★★」[DataContract(Namespace="")]

언급URL : https://stackoverflow.com/questions/627356/how-to-not-serialize-the-type-property-on-json-objects

반응형