programing

웹 API를 통해 전송된 문자열은 따옴표로 둘러싸여 있습니다.

newnotes 2023. 3. 31. 22:37
반응형

웹 API를 통해 전송된 문자열은 따옴표로 둘러싸여 있습니다.

ASP의 웹 API에 작은 문제가 발생했습니다.NET 4, C# 사용.여러 웹 API를 통해 데이터를 주고받는 프런트 엔드 GUI를 만들려고 합니다.API가 여러 개 있는 이유는 여러 개의 보안 구역으로 구성된 네트워크와 관련이 있습니다.서버는 서로 다른 영역에 배치되어 있으며, 단순한 요청은 3개의 다른 API를 통과해야 할 수 있습니다.

구체적으로는 GUI에서 첫 번째 API로 JSON 오브젝트를 보냅니다.JSON 오브젝트는 다음 API와 다음 API로 전송되어야 하며, 여기서 새로운 JSON 오브젝트가 생성되어 동일한 경로로 반환됩니다.

경로 자체는 잘 작동합니다.문제는 JSON 오브젝트가 GUI로 돌아가면 해석할 수 없다는 것입니다.API마다 한 번씩 따옴표로 둘러싸인 JSON 문자열을 받고 있습니다.

문자열은 다음과 같이 시작할 수 있습니다.

Hey! I am a string, or a JSON object of sorts!

API 사이의 첫 번째 홉은 다음과 같습니다.

"Hey! I am a string, or a JSON object of sorts!"

넥스트 홉 후에는 다음과 같이 됩니다.

"\"Hey! I am a string, or a JSON object of sorts!\""

GUI가 입수하면, 다음과 같은 것이 표시됩니다.

"\"\\\"Hey! I am a string, or a JSON object of sorts!\\\"\""

여기서 명백한 이유로 해석에 실패합니다.JSON 오브젝트 자체의 형식은 적절하지만, 모든 따옴표로 인해 JSON.net 파서에 문제가 발생하고 있습니다(오브젝트 내부의 모든 따옴표도 여러 번 감겨져 있습니다).

지금까지 시도했던 것은 어플리케이션/json 타입과 text/plain 타입으로 요청을 보내는 것입니다.둘 다 같은 일을 했다.API는 HttpResponseMessage를 반환합니다.HttpResponseMessage는 ReadAsStringAsync()를 사용하여 읽습니다.문자열 읽기를 피하고 HttpRequestMessage에서 HttpResponseMessage로 직접 읽어보고 GUI에서만 ReadAsStringAsync()를 실행하려고 했지만 문제는 해결되지 않았습니다.JSON 문자열은 JSON.nets Serialize()-method를 사용하여 생성되며 StringContent()를 사용하여 HttpContent에 저장됩니다.이것으로 올바르게 동작하고 있는 것 같습니다.API와 GUI가 HttpResponseMessage를 수신할 때 견적이 생성된다고 생각합니다.

JSON 스트링을 가공되지 않은 스트링으로 송수신하는 방법을 알고 계십니까?

오브젝트를 각 API에서 JToken 또는 JObject로 해석하여 다시 시리얼화함으로써 이 동작을 우회할 수 있습니다.그러나 이는 좋은 해결책이 아닙니다.API는 메시지를 받은 그대로 전송하고 아무것도 하지 않는 것이 좋습니다.루팅을 사용하여 포워드를 조사했습니다만, 리다이렉트 루트가 아닌 API 액션을 사용해야 하는 인증이 많이 이루어지고 있습니다.

명확히 하기(TLDR):이상적인 해결책은 API가 메시지를 해석하거나 읽지 않고 단순히 전달하는 것입니다.메시지 소스가 인증되고 요청이 암호화되며 요청된 URL이 유효하다면 메시지 자체는 각 "프록시" API에 큰 문제가 되지 않습니다.

따옴표와 백슬래시는 응답을 수신했을 때가 아니라 각 응답에 대해 JSON 문자열이 다시 직렬화되기 때문에 각 "프록시" API에 추가됩니다.

프록시 API에서는 다음과 같은 작업을 수행할 수 있습니다(간단히 하기 위해 오류 처리 생략).

[HttpGet]
public async Task<HttpResponseMessage> GetWidget(int id)
{
    HttpClient client = new HttpClient();
    string url = "http://nextapiserver.example.org/widgets/" + id;
    string json = await client.GetStringAsync(url);
    return Request.CreateResponse(HttpStatusCode.OK, json);
}

여기서의 문제는 Web API가 기본적으로 사용자가 제공하는 모든 것을 직렬화하는 것을 담당한다고 가정한다는 것입니다.대부분의 사용 사례에서 이것이 바로 여러분이 원하는 것입니다.그러나 콘텐츠가 JSON에 이미 직렬화되어 있는 경우 웹 API는 이를 알 수 없습니다. 이 과정에서 문자열을 다시 직렬화하고 추가 따옴표와 백슬래시를 추가합니다.

JSON 문자열을 그대로 통과시키려면 응답 콘텐츠개체를 명시적으로 작성해야 합니다(Web API에 의해 작성되는 것이 아니라). 미디어 유형을 로 설정하여 다운스트림클라이언트가 JSON(일반 텍스트가 아닌)으로 해석할 수 있도록 해야 합니다.수정된 코드는 다음과 같습니다.

[HttpGet]
public async Task<HttpResponseMessage> GetWidget(int id)
{
    HttpClient client = new HttpClient();
    string url = "http://nextapiserver.example.org/widgets/" + id;
    string json = await client.GetStringAsync(url);
    HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);
    response.Content = new StringContent(json, Encoding.UTF8, "application/json");
    return response;
}

위의 내용이 개선될 수 있다고 생각합니다만, 그것이 요점입니다.한 번 시도해 보고 문제가 해결되는지 확인해 보세요.이 수정은 모든 프록시 API에 적용해야 합니다.

ASP asp asp 。 Core, NET Core로 합니다.[Produces("text/plain")].

예.

[HttpGet("/"), Produces("text/plain")]
public IActionResult HelloWorld() => Ok("Hello World");

많은 연구 끝에, 마침내 이 문제를 알아냈어요.

먼저 HttpResponseMessage를 직접 반환했습니다.API 경로를 따라 각 홉 내에서 의도적으로 역직렬화하지 않았습니다.

문제는 실제로 우리가 "mvc serialization" 방식과 JSON.net의 방식을 혼합하여 사용하고 있다는 것입니다.어느 것 하나만으로도 충분하며 모든 API의 클린 패스스루를 제공합니다.그러나 네이티브 메서드와 JSON.net-module의 시리얼화된 데이터를 결합하면 API는 포맷을 인식하지 못하고 콘텐츠를 다시 시리얼화해야 한다고 잘못 가정합니다(네이티브 메서드를 사용).

그 때문에, 시리얼라이제이션 프로세스로부터 JSON.net를 모두 삭제하는 것만으로, 예상대로의 결과를 얻을 수 있었습니다.

이것은 모두를 위한 것은 아니지만 Microsoft의 Ok() IAction Result를 사용하고 싶었습니다.AspNetCore.완전한 HttpResponseMessage를 실행하는 대신 MVC를 사용합니다.문자열 결과도 따옴표로 묶었습니다.

"\"my string result\""

문자열을 반환하는 대신 속성을 가진 개체를 반환했습니다.원래의 문제의 예:

return Ok(myStringValue);

나에게 효과가 있었던 것:

return Ok(new { id = myStringValue });

이는 요청 접수 측면에서 좀 더 설명적인 이점이 있었습니다.

이 문제가 있어서 설치했습니다.Newtonsoft.JsonNuget Packages Manager 경유.다음으로 JSON 문자열을 역직렬화하려면 다음 절차를 수행합니다.

string deserializedString = JsonConvert.DeserializeObject<string>(yourJsonString);

네임스페이스를 가져오는 것을 잊지 마십시오.

using Newtonsoft.Json;

이 스레드 제목과 같은 증상이 있었지만, 다른 문제가 발생할 수 있습니다.SQL Server 2016의 JSON 데이터가 들어 있는 열이 있습니다(권장되는 nvarchar SQL 데이터 유형에 저장됨).브라우저에서 WEB API를 눌렀을 때 JSON 열의 모든 이중 따옴표가 이스케이프되었습니다(백슬래시 따옴표).javascript GUI에서 JSON.parse를 실행 중이어서 JSON 데이터를 참조할 수 없었습니다.처음에는 백슬래시 등이 문제라고 생각했습니다.하지만 제 Javascript 코드는 이스케이프 코드로는 정상적으로 동작할 수 있었습니다.진짜 문제는 컬럼 데이터에서 JSON.parse를 실행하기 전에 하위 레벨에서 JSON 데이터를 참조 해제하려고 했던 것입니다.

좀 더 구체적으로 말하면, DB의 한 행의 데이터가 json('애플리케이션/json' 데이터가 브라우저로 반환됨)으로 반환된다고 가정해 보십시오.lets call은 myJSONdata 입니다.모든 열의 모든 데이터는 JSON으로 반환되지만 특정 열(myJ라고 함)은 1개입니다.SONcolumn)에는 수레벨의 JSON 오브젝트가 있습니다.

다음과 같은 서브레벨의 디레퍼런스는 실패합니다.

JSON.parse(myJSONdata["myJSONcolumn"]["sublevel1"])

이 방법은 유효합니다.

JSON.parse(myJSONdata["myJSONcolumn"])["sublevel1"]

는 용 i i용었 i i i i i 。Microsoft.AspNetCore.Mvc@ctc @ @ API @ @ @ 예:

var myStringValue = "string value";
return Ok(myStringValue);

한 후 않게 .DefaultRequestHeaders.Accept로로 합니다.application/json.

오리지널 코드

var client = new HttpClient();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var request = new HttpRequestMessage(HttpMethod.Post, "http://<Host>/<Path>");
request.Content = new StringContent(requestBody, Encoding.UTF8, "application/json");
var httpResponseMessage = client.SendAsync(request).Result;
var responseString = httpResponseMessage.Content.ReadAsStringAsync().Result;

vs modified version (위 스니펫의 두 번째 줄 추가)

var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "http://<Host>/<Path>");
request.Content = new StringContent(requestBody, Encoding.UTF8, "application/json");
var httpResponseMessage = client.SendAsync(request).Result;
var responseString = httpResponseMessage.Content.ReadAsStringAsync().Result;

헤더를 으로써 accept는 accept 헤더를 할 수 .HttpResponseMessage는, 이 경우, 「」, 「accept」, 「accept」, 「accept」, 「accept」라고 합니다.application/json.

은 '수락'을 .text/plain 전에application/json그게해!

★★★의 HttpClient

_client = new HttpClient()
{
    BaseAddress = new Uri("https://localhost:7267/")
};
_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain")); // Should be first
_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

요청별 초기화: https://stackoverflow.com/a/52458995/3351489

★★★★★★★★★★★★★에서도 같은 문제가 있었습니다.System.Web.Http.ApiController를입니다.JsonHelper 클래스입니다.Newtonsoft.Json.JsonConvert

var jason = JsonHelper.SerializeToJson(result);
return Ok(jason);

같은 가 초래되었습니다."\"{ ... }\"" 프로세스에관한 특정 규칙이 에 사전 했습니다.시리얼화 프로세스에 관한 몇 가지 특정 규칙이 있기 때문에 사전 시리얼화가 필요했습니다.

운운이 System.Web.Http.Results.JsonResult<T>을 사용법

return new JsonResult<MyDataType>(result, JsonHelper.Settings, Encoding.UTF8, this);

ASP를 사용하는 경우.NET 최소 API를 사용할 수 있는 방법이 있습니다.

app.MapGet("/HelloWorld", () => Results.Text("Hello, World"))

같은 안 될 것 같았습니다.[Produces(MediaTypeNames.Text.Plain)] 제거하다[Produces(MediaTypeNames.Application.Json)]문제를 해결합니다.

products json Atribut을 추가하면 결과가 시리얼화됩니다.이 경우 이미 문자열일 경우 따옴표가 추가됩니다.

하시면 됩니다.GetAsyncGetStringAsync

public async Task<HttpResponseMessage> Get(int id)
{
    using (HttpClient httpClient = new HttpClient())
    {
        return await httpClient.GetAsync(url);
    }
}

검증 코드와 응답 코드를 처리합니다.

언급URL : https://stackoverflow.com/questions/33681978/strings-sent-through-web-apis-gets-wrapped-in-quotes

반응형