ASP.NET Core Web API에서 응답 데이터 서식 지정

ASP.NET Core MVC는 지정된 형식을 사용하거나 클라이언트의 요청에 대한 응답으로 응답 데이터의 서식 지정을 지원합니다.

형식별 작업 결과

일부 작업 결과 형식은 JsonResultContentResult와 같이 특정 형식과 관련됩니다. 작업은 다른 형식에 대한 클라이언트의 요청을 무시하고 항상 지정된 형식을 사용하는 결과를 반환할 수 있습니다. 예를 들어 JsonResult 반환은 JSON 형식의 데이터를 반환하고 ContentResult 반환은 일반 텍스트 형식 문자열 데이터를 반환합니다.

특정 형식을 반환하는 작업은 필요하지 않습니다. ASP.NET Core는 모든 개체 반환 값을 지원합니다. IActionResult 형식이 아닌 개체를 반환하는 작업의 결과는 적절한 IOutputFormatter 구현을 사용하여 직렬화됩니다. 자세한 내용은 ASP.NET Core 웹 API의 컨트롤러 작업 반환 형식을 참조하세요.

기본적으로 기본 제공 도우미 메서드 ControllerBase.Ok는 JSON 형식 데이터를 반환합니다.

[HttpGet]
public IActionResult Get() =>
    Ok(_todoItemStore.GetList());

샘플 코드는 할 일 항목의 목록을 반환합니다. F12 브라우저 개발자 도구 또는 이전 코드와 함께 http-repl 을 사용하면 다음이 표시됩니다.

  • content-type:application/json; charset=utf-8을 포함하는 응답 헤더.
  • 요청 헤더입니다. 예를 들어 Accept 헤더가 있습니다. Accept 헤더는 앞의 코드에서 무시됩니다.

서식 있는 일반 텍스트 데이터를 반환하려면 ContentResultContent 도우미를 사용합니다.

[HttpGet("Version")]
public ContentResult GetVersion() =>
    Content("v1.0.0");

위의 코드에서 반환된 Content-Typetext/plain입니다.

반환 형식이 여러 개인 작업의 경우 IActionResult를 반환합니다. 예를 들어 작업의 결과에 따라 서로 다른 HTTP 상태 코드를 반환하는 경우입니다.

콘텐츠 협상

콘텐츠 협상은 클라이언트가 헤더 수락을 지정하는 경우 발생합니다. ASP.NET Core에서 사용하는 기본 형식은 JSON입니다. 콘텐츠 협상은 다음과 같은 특징을 가집니다.

  • ObjectResult에 의해 구현됩니다.
  • 도우미 메서드에서 반환된 상태 코드별 작업 결과 상태 코드에 기본적으로 제공됩니다. 작업 결과 도우미 메서드는 ObjectResult를 기반으로 합니다.

모델 형식이 반환되는 경우 반환 형식은 ObjectResult입니다.

다음 작업 메서드는 OkNotFound 도우미 메서드를 사용합니다.

[HttpGet("{id:long}")]
public IActionResult GetById(long id)
{
    var todo = _todoItemStore.GetById(id);

    if (todo is null)
    {
        return NotFound();
    }

    return Ok(todo);
}

기본적으로 ASP.NET Core는 다음 미디어 유형을 지원합니다.

  • application/json
  • text/json
  • text/plain

Fiddler 또는 Postman과 같은 도구는 반환 형식을 지정하도록 Accept 요청 헤더를 설정할 수 있습니다. Accept 헤더에 서버가 지원하는 형식이 포함되어 있으면 해당 형식이 반환됩니다. 다음 섹션에서는 추가적인 포맷터를 추가하는 방법을 보여줍니다.

컨트롤러 작업은 POCO(Plain Old CLR Objects)를 반환할 수 있습니다. POCO가 반환되면 런타임에서는 개체를 래핑하는ObjectResult를 자동으로 만듭니다. 클라이언트는 형식이 지정된 직렬화된 개체를 가져옵니다. 반환되는 개체가 null이면 204 No Content 응답이 반환됩니다.

다음 예제에서는 개체 형식을 반환합니다.

[HttpGet("{id:long}")]
public TodoItem? GetById(long id) =>
    _todoItemStore.GetById(id);

앞의 코드에서 유효한 할 일 항목에 대한 요청은 200 OK 응답을 반환합니다. 잘못된 할 일 항목에 대한 요청은 204 No Content 응답을 반환합니다.

Accept 헤더

콘텐츠 협상Accept 헤더가 요청에 나타나는 경우에 발생합니다. 요청에 Accept 헤더가 포함되어 있으면 ASP.NET Core는 다음을 수행합니다.

  • 기본 설정 순서에 따라 Accept 헤더의 미디어 형식을 열거합니다.
  • 지정된 형식 중 하나로 응답을 생성할 수 있는 포맷터를 찾으려고 시도합니다.

클라이언트의 요청을 충족할 수 있는 포맷터가 없는 경우 ASP.NET Core는 다음을 수행합니다.

  • MvcOptions.ReturnHttpNotAcceptabletrue로 설정된 경우 406 Not Acceptable을 반환합니다. 또는
  • 응답을 생성할 수 있는 첫 번째 포맷터를 찾으려고 시도합니다.

요청된 형식에 대해 포맷터가 구성되지 않은 경우에는 개체의 서식을 지정할 수 있는 첫 번째 포맷터가 사용됩니다. 요청에 Accept 헤더가 표시되지 않을 경우 다음이 수행됩니다.

  • 개체를 처리할 수 있는 첫 번째 포맷터는 응답을 직렬화하는 데 사용됩니다.
  • 발생하는 협상이 없습니다. 서버에서 반환할 형식을 결정합니다.

Accept 헤더에 */*가 포함되는 경우, RespectBrowserAcceptHeaderMvcOptions에서 true로 설정되지 않으면 헤더는 무시됩니다.

브라우저 및 콘텐츠 협상

일반적인 API 클라이언트와 달리 웹 브라우저는 Accept 헤더를 제공합니다. 웹 브라우저는 와일드카드를 비롯한 다양한 형식을 지정합니다. 기본적으로 프레임워크가 브라우저에서 요청이 수신되는 것을 감지할 경우 다음이 수행됩니다.

  • Accept 헤더는 무시됩니다.
  • 달리 구성되지 않은 경우 콘텐츠가 JSON에 반환됩니다.

이 접근 방식은 API를 소비할 때 브라우저에서 보다 일관된 환경을 제공합니다.

브라우저 허용 헤더를 준수하도록 앱을 구성하려면 RespectBrowserAcceptHeader 속성을 true로 설정합니다.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers(options =>
{
    options.RespectBrowserAcceptHeader = true;
});

포맷터 구성

추가 형식을 지원해야 하는 앱은 적절한 NuGet 패키지를 추가하고 지원을 구성할 수 있습니다. 입력 및 출력에 대한 개별 포맷터가 있습니다. 입력 포맷터는 모델 바인딩에서 사용됩니다. 출력 포맷터는 응답의 형식을 지정하는 데 사용됩니다. 사용자 지정 포맷터 생성에 대한 정보는 사용자 지정 포맷터를 참조하세요.

XML 형식 지원 추가

XmlSerializer를 사용하여 구현된 XML 포맷터를 구성하려면 AddXmlSerializerFormatters를 호출합니다.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers()
    .AddXmlSerializerFormatters();

위의 코드를 사용할 때 컨트롤러 메서드는 요청의 Accept 헤더에 따라 적절한 형식을 반환합니다.

System.Text.Json 기반 포맷터 구성

System.Text.Json 기반 포맷터에 대한 기능을 구성하려면 Microsoft.AspNetCore.Mvc.JsonOptions.JsonSerializerOptions를 사용합니다. 다음 강조 표시된 코드는 기본 camelCase 서식 대신 PascalCase 서식을 구성합니다.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers()
    .AddJsonOptions(options =>
    {
        options.JsonSerializerOptions.PropertyNamingPolicy = null;
    });

다음 작업 메서드는 응답을 만들기 위해 호출 ControllerBase.Problem 합니다.ProblemDetails

[HttpGet("Error")]
public IActionResult GetError() =>
    Problem("Something went wrong.");

앱이 형식을 PascalCase로 설정하더라도 ProblemDetails 응답은 항상 camelCase입니다. ProblemDetails는 소문자를 지정하는 RFC 7807을 따릅니다.

특정 작업에 대한 출력 serialization 옵션을 구성하려면 JsonResult를 사용합니다. 예시:

[HttpGet]
public IActionResult Get() =>
    new JsonResult(
        _todoItemStore.GetList(),
        new JsonSerializerOptions
        {
            PropertyNamingPolicy = null
        });

Newtonsoft.Json 기반 JSON 형식 지원 추가

기본 JSON 포맷터는 System.Text.Json을 사용합니다. Newtonsoft.Json 기반 포맷터를 사용하려면 Microsoft.AspNetCore.Mvc.NewtonsoftJson NuGet 패키지를 설치하고 Program.cs에서 구성합니다.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers()
    .AddNewtonsoftJson();

위의 코드에서 AddNewtonsoftJson에 대한 호출은 Newtonsoft.Json을 사용하도록 다음 Web API, MVC 및 Razor Pages 기능을 구성합니다.

일부 기능은 System.Text.Json 기반 포맷터와 잘 호환되지 않고 Newtonsoft.Json 기반 포맷터에 대한 참조를 필요로 할 수 있습니다. 앱이 다음과 같은 경우 Newtonsoft.Json 기반 포맷터를 계속해서 사용합니다.

  • Newtonsoft.Json 속성을 사용합니다. 예를 들어 [JsonProperty] 또는 [JsonIgnore]입니다.
  • 직렬화 설정을 사용자 지정합니다.
  • Newtonsoft.Json은 제공하는 기능에 의존합니다.

Newtonsoft.Json 기반 포맷터에 대한 기능을 구성하려면 SerializerSettings를 사용합니다.

builder.Services.AddControllers()
    .AddNewtonsoftJson(options =>
    {
        options.SerializerSettings.ContractResolver = new DefaultContractResolver();
    });

특정 작업에 대한 출력 serialization 옵션을 구성하려면 JsonResult를 사용합니다. 예시:

[HttpGet]
public IActionResult GetNewtonsoftJson() =>
    new JsonResult(
        _todoItemStore.GetList(),
        new JsonSerializerSettings
        {
            ContractResolver = new DefaultContractResolver()
        });

형식 지정

응답 형식을 제한하려면 [Produces] 필터를 적용합니다. 대부분 필터와 마찬가지로, [Produces]는 작업, 컨트롤러 또는 전역 범위에 적용할 수 있습니다.

[ApiController]
[Route("api/[controller]")]
[Produces("application/json")]
public class TodoItemsController : ControllerBase

위의 [Produces] 필터:

  • 컨트롤러 내의 모든 작업이 POCO(일반 이전 CLR 개체) 또는 ObjectResult 파생 형식에 대한 JSON 형식 응답을 반환하도록 합니다.
  • 다른 포맷터가 구성되고 클라이언트가 다른 형식을 지정하는 경우에도 JSON 형식 응답을 반환합니다.

자세한 내용은 필터를 참조하세요.

특수한 사례 포맷터

일부 특수한 경우 기본 제공 포맷터를 사용하여 구현됩니다. 기본적으로 string 반환 형식은 text/plain(Accept 헤더를 통해 요청된 경우 text/html)으로 형식이 지정됩니다. 이 동작은 StringOutputFormatter를 제거하여 삭제할 수 있습니다. 포맷터는 Program.cs에서 제거됩니다. 모델 개체 반환 형식이 있는 작업은 null을 반환하는 경우 204 No Content를 반환합니다. 이 동작은 HttpNoContentOutputFormatter를 제거하여 삭제할 수 있습니다. 다음 코드를 StringOutputFormatterHttpNoContentOutputFormatter를 제거합니다.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers(options =>
{
    // using Microsoft.AspNetCore.Mvc.Formatters;
    options.OutputFormatters.RemoveType<StringOutputFormatter>();
    options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
});

StringOutputFormatter가 없으면 기본 제공 JSON 포맷터가 string 반환 형식의 형식을 지정합니다. 기본 제공 JSON 포맷터가 제거되고 XML 포맷터를 사용할 수 있는 경우, XML 포맷터가 string 반환 형식의 형식을 지정합니다. 그렇지 않으면 string 반환 형식이 406 Not Acceptable을 반환합니다.

HttpNoContentOutputFormatter가 없으면 null 개체는 구성된 포맷터를 사용하여 서식이 지정됩니다. 예시:

  • JSON 포맷터는 null의 본문이 포함된 응답을 반환합니다.
  • XML 포맷터는 xsi:nil="true"로 설정된 특성을 사용하여 빈 XML 요소를 반환합니다.

응답 형식 URL 매핑

클라이언트는 URL의 일부로 특정 형식을 요청할 수 있습니다. 예를 들면 다음과 같습니다.

  • 쿼리 문자열 또는 경로의 부분에서.
  • .Xml 또는 .json과 같은 서식 지정 파일 확장명을 사용하여.

요청 경로의 매핑은 API가 사용하는 경로에 지정해야 합니다. 예시:

[ApiController]
[Route("api/[controller]")]
[FormatFilter]
public class TodoItemsController : ControllerBase
{
    private readonly TodoItemStore _todoItemStore;

    public TodoItemsController(TodoItemStore todoItemStore) =>
        _todoItemStore = todoItemStore;

    [HttpGet("{id:long}.{format?}")]
    public TodoItem? GetById(long id) =>
        _todoItemStore.GetById(id);

위 경로를 사용하면 요청된 형식을 선택적 파일 확장명을 사용하여 지정할 수 있습니다. [FormatFilter] 특성은 RouteData에서 형식 값의 존재 여부를 검사하며, 응답이 생성될 때 응답 형식을 적절한 포맷터에 매핑합니다.

경로 포맷터
/api/todoitems/5 기본 출력 포맷터
/api/todoitems/5.json JSON 포맷터(구성된 경우)
/api/todoitems/5.xml XML 포맷터(구성된 경우)

다형 역직렬화

기본 제공 기능을 통해 제한적으로 다형 serialization을 제공할 수 있지만 deserialization은 전혀 지원되지 않습니다. deserialization을 수행하려면 사용자 지정 변환기가 필요합니다. 다형 역직렬화의 전체 샘플은 다형 역직렬화를 참조하세요.

추가 리소스

ASP.NET Core MVC는 응답 데이터 서식 지정을 지원합니다. 응답 데이터는 특정 형식 또는 클라이언트 요청 형식에 대한 응답으로 형식을 지정할 수 있습니다.

샘플 코드 보기 및 다운로드(다운로드 방법)

형식별 작업 결과

일부 작업 결과 형식은 JsonResultContentResult와 같이 특정 형식과 관련됩니다. 작업은 클라이언트 기본 설정에 관계 없이 특정 형식으로 서식이 지정된 결과를 반환할 수 있습니다. 예를 들어 JsonResult를 반환하면 JSON 형식의 데이터가 반환됩니다. ContentResult 또는 문자열 하나를 반환하면 일반 텍스트 형식의 문자열 데이터가 반환됩니다.

특정 형식을 반환하는 작업은 필요하지 않습니다. ASP.NET Core는 모든 개체 반환 값을 지원합니다. IActionResult 형식이 아닌 개체를 반환하는 작업의 결과는 적절한 IOutputFormatter 구현을 사용하여 직렬화됩니다. 자세한 내용은 ASP.NET Core 웹 API의 컨트롤러 작업 반환 형식을 참조하세요.

기본 제공 도우미 메서드 Ok는 다음 JSON 형식 데이터를 반환합니다.

// GET: api/authors
[HttpGet]
public ActionResult Get()
{
    return Ok(_authors.List());
}

샘플 다운로드는 작성자 목록을 반환합니다. 이전 코드와 함께 F12 브라우저 개발자 도구 또는 http-repl 사용:

  • content-type:이 포함된 응답 헤더 application/json; charset=utf-8이 표시됩니다.
  • 요청 헤더가 표시됩니다. 예를 들어 Accept 헤더가 있습니다. Accept 헤더는 앞의 코드에서 무시됩니다.

서식 있는 일반 텍스트 데이터를 반환하려면 ContentResultContent 도우미를 사용합니다.

// GET api/authors/about
[HttpGet("About")]
public ContentResult About()
{
    return Content("An API listing authors of docs.asp.net.");
}

위의 코드에서 반환된 Content-Typetext/plain입니다. 문자열을 반환하면 text/plainContent-Type이 제공됩니다.

// GET api/authors/version
[HttpGet("version")]
public string Version()
{
    return "Version 1.0.0";
}

반환 형식이 여러 개인 작업의 경우 IActionResult를 반환합니다. 예를 들어 수행된 작업의 결과에 따라 서로 다른 HTTP 상태 코드를 반환합니다.

콘텐츠 협상

콘텐츠 협상은 클라이언트가 헤더 수락을 지정하는 경우 발생합니다. ASP.NET Core에서 사용하는 기본 형식은 JSON입니다. 콘텐츠 협상은 다음과 같은 특징을 가집니다.

  • ObjectResult에 의해 구현됩니다.
  • 도우미 메서드에서 반환된 상태 코드별 작업 결과 상태 코드에 기본적으로 제공됩니다. 작업 결과 도우미 메서드는 ObjectResult를 기반으로 합니다.

모델 형식이 반환되는 경우 반환 형식은 ObjectResult입니다.

다음 작업 메서드는 OkNotFound 도우미 메서드를 사용합니다.

// GET: api/authors/search?namelike=th
[HttpGet("Search")]
public IActionResult Search(string namelike)
{
    var result = _authors.GetByNameSubstring(namelike);
    if (!result.Any())
    {
        return NotFound(namelike);
    }
    return Ok(result);
}

기본적으로 ASP.NET Core는 application/json, text/json, text/plain 미디어 형식을 지원합니다. Fiddler 또는 http-repl과 같은 도구는 요청 헤더를 Accept 설정하여 반환 형식을 지정할 수 있습니다. Accept 헤더에 서버가 지원하는 형식이 포함되어 있으면 해당 형식이 반환됩니다. 다음 섹션에서는 추가적인 포맷터를 추가하는 방법을 보여줍니다.

컨트롤러 작업은 POCO(Plain Old CLR Objects)를 반환할 수 있습니다. POCO가 반환되면 런타임에서는 개체를 래핑하는ObjectResult를 자동으로 만듭니다. 클라이언트는 형식이 지정된 직렬화된 개체를 가져옵니다. 반환되는 개체가 null이면 204 No Content 응답이 반환됩니다.

개체 형식 반환하기:

// GET api/authors/RickAndMSFT
[HttpGet("{alias}")]
public Author Get(string alias)
{
    return _authors.GetByAlias(alias);
}

위 코드에서는 유효한 작성자 별칭에 대한 요청이 작성자의 데이터와 함께 200 OK 응답을 반환합니다. 잘못된 별칭에 대한 요청은 204 No Content 응답을 반환합니다.

Accept 헤더

콘텐츠 협상Accept 헤더가 요청에 나타나는 경우에 발생합니다. 요청에 Accept 헤더가 포함되어 있으면 ASP.NET Core는 다음을 수행합니다.

  • 기본 설정 순서에 따라 Accept 헤더의 미디어 형식을 열거합니다.
  • 지정된 형식 중 하나로 응답을 생성할 수 있는 포맷터를 찾으려고 시도합니다.

클라이언트의 요청을 충족할 수 있는 포맷터가 없는 경우 ASP.NET Core는 다음을 수행합니다.

  • MvcOptions.ReturnHttpNotAcceptabletrue로 설정된 경우 406 Not Acceptable을 반환합니다. 또는
  • 응답을 생성할 수 있는 첫 번째 포맷터를 찾으려고 시도합니다.

요청된 형식에 대해 포맷터가 구성되지 않은 경우에는 개체의 서식을 지정할 수 있는 첫 번째 포맷터가 사용됩니다. 요청에 Accept 헤더가 표시되지 않을 경우 다음이 수행됩니다.

  • 개체를 처리할 수 있는 첫 번째 포맷터는 응답을 직렬화하는 데 사용됩니다.
  • 발생하는 협상이 없습니다. 서버에서 반환할 형식을 결정합니다.

Accept 헤더에 */*가 포함되는 경우, RespectBrowserAcceptHeaderMvcOptions에서 true로 설정되지 않으면 헤더는 무시됩니다.

브라우저 및 콘텐츠 협상

일반적인 API 클라이언트와 달리 웹 브라우저는 Accept 헤더를 제공합니다. 웹 브라우저는 와일드카드를 비롯한 다양한 형식을 지정합니다. 기본적으로 프레임워크가 브라우저에서 요청이 수신되는 것을 감지할 경우 다음이 수행됩니다.

  • Accept 헤더는 무시됩니다.
  • 달리 구성되지 않은 경우 콘텐츠가 JSON에 반환됩니다.

이 접근 방식은 API를 소비할 때 브라우저에서 보다 일관된 환경을 제공합니다.

브라우저 Accept 헤더를 적용하도록 앱을 구성하려면 RespectBrowserAcceptHeadertrue로 설정합니다.

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers(options =>
    {
        options.RespectBrowserAcceptHeader = true; // false by default
    });
}

포맷터 구성

추가 형식을 지원해야 하는 앱은 적절한 NuGet 패키지를 추가하고 지원을 구성할 수 있습니다. 입력 및 출력에 대한 개별 포맷터가 있습니다. 입력 포맷터는 모델 바인딩에서 사용됩니다. 출력 포맷터는 응답의 형식을 지정하는 데 사용됩니다. 사용자 지정 포맷터 생성에 대한 정보는 사용자 지정 포맷터를 참조하세요.

XML 형식 지원 추가

XmlSerializer를 사용하여 구현된 XML 포맷터는 AddXmlSerializerFormatters를 호출하여 구성됩니다.

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers()
        .AddXmlSerializerFormatters();
}

위의 코드는 XmlSerializer를 사용하여 결과를 직렬화합니다.

위의 코드를 사용할 때 컨트롤러 메서드는 요청의 Accept 헤더에 따라 적절한 형식을 반환합니다.

System.Text.Json 기반 포맷터 구성

System.Text.Json 기반 포맷터의 기능은 Microsoft.AspNetCore.Mvc.JsonOptions.JsonSerializerOptions을 사용하여 구성할 수 있습니다. 기본 서식은 camelCase입니다. 다음 강조 표시된 코드는 PascalCase 서식을 설정합니다.

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers()
        .AddJsonOptions(options =>
            options.JsonSerializerOptions.PropertyNamingPolicy = null);
}

다음 작업 메서드는 응답을 만들기 위해 호출 ControllerBase.Problem 합니다.ProblemDetails

[HttpGet("error")]
public IActionResult GetError()
{
    return Problem("Something went wrong!");
}

위의 코드를 사용하여 다음을 수행합니다.

  • https://localhost:5001/WeatherForecast/temperature는 PascalCase를 반환합니다.
  • https://localhost:5001/WeatherForecast/error는 camelCase를 반환합니다. 앱이 형식을 PascalCase로 설정하더라도 오류 응답은 항상 camelCase입니다. ProblemDetails는 소문자를 지정하는 RFC 7807을 따릅니다.

다음 코드는 PascalCase를 설정하고 사용자 지정 변환기를 추가합니다.

services.AddControllers().AddJsonOptions(options =>
{
    // Use the default property (Pascal) casing.
    options.JsonSerializerOptions.PropertyNamingPolicy = null;

    // Configure a custom converter.
    options.JsonSerializerOptions.Converters.Add(new MyCustomJsonConverter());
});

JsonResult를 사용하여 동작 단위로 출력 serialization 옵션을 구성할 수 있습니다. 예시:

public IActionResult Get()
{
    return Json(model, new JsonSerializerOptions
    {
        WriteIndented = true,
    });
}

Newtonsoft.Json 기반 JSON 형식 지원 추가

기본 JSON 포맷터는 System.Text.Json을 기반으로 합니다. Newtonsoft.Json 기반 포맷터 및 기능에 대한 지원은 Microsoft.AspNetCore.Mvc.NewtonsoftJson NuGet 패키지를 설치하고 Startup.ConfigureServices에서 구성하여 이용할 수 있습니다.

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers()
        .AddNewtonsoftJson();
}

위의 코드에서 AddNewtonsoftJson에 대한 호출은 Newtonsoft.Json을 사용하도록 다음 Web API, MVC 및 Razor Pages 기능을 구성합니다.

일부 기능은 System.Text.Json 기반 포맷터와 잘 호환되지 않고 Newtonsoft.Json 기반 포맷터에 대한 참조를 필요로 할 수 있습니다. 앱이 다음과 같은 경우 Newtonsoft.Json 기반 포맷터를 계속해서 사용합니다.

  • Newtonsoft.Json 속성을 사용합니다. 예를 들어 [JsonProperty] 또는 [JsonIgnore]입니다.
  • 직렬화 설정을 사용자 지정합니다.
  • Newtonsoft.Json은 제공하는 기능에 의존합니다.

Newtonsoft.Json 기반 포맷터의 기능은 Microsoft.AspNetCore.Mvc.MvcNewtonsoftJsonOptions.SerializerSettings를 사용하여 구성할 수 있습니다.

services.AddControllers().AddNewtonsoftJson(options =>
{
    // Use the default property (Pascal) casing
    options.SerializerSettings.ContractResolver = new DefaultContractResolver();

    // Configure a custom converter
    options.SerializerSettings.Converters.Add(new MyCustomJsonConverter());
});

JsonResult를 사용하여 동작 단위로 출력 serialization 옵션을 구성할 수 있습니다. 예시:

public IActionResult Get()
{
    return Json(model, new JsonSerializerSettings
    {
        Formatting = Formatting.Indented,
    });
}

형식 지정

응답 형식을 제한하려면 [Produces] 필터를 적용합니다. 대부분 필터와 마찬가지로, [Produces]는 작업, 컨트롤러 또는 전역 범위에 적용할 수 있습니다.

[ApiController]
[Route("[controller]")]
[Produces("application/json")]
public class WeatherForecastController : ControllerBase
{

위의 [Produces] 필터:

  • 컨트롤러 내의 모든 작업이 POCO(일반 이전 CLR 개체) 또는 ObjectResult 파생 형식에 대한 JSON 형식 응답을 반환하도록 합니다.
  • 다른 포맷터가 구성되고 클라이언트에서 다른 형식을 지정하는 경우 JSON이 반환됩니다.

자세한 내용은 필터를 참조하세요.

특수한 사례 포맷터

일부 특수한 경우 기본 제공 포맷터를 사용하여 구현됩니다. 기본적으로 string 반환 형식은 text/plain(Accept 헤더를 통해 요청된 경우 text/html)으로 형식이 지정됩니다. 이 동작은 StringOutputFormatter를 제거하여 삭제할 수 있습니다. 포맷터들은 ConfigureServices 방법에서 제거됩니다. 모델 개체 반환 형식이 있는 작업은 null을 반환하는 경우 204 No Content를 반환합니다. 이 동작은 HttpNoContentOutputFormatter를 제거하여 삭제할 수 있습니다. 다음 코드를 StringOutputFormatterHttpNoContentOutputFormatter를 제거합니다.

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers(options =>
    {
        // requires using Microsoft.AspNetCore.Mvc.Formatters;
        options.OutputFormatters.RemoveType<StringOutputFormatter>();
        options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
    });
}

StringOutputFormatter가 없으면 기본 제공 JSON 포맷터가 string 반환 형식의 형식을 지정합니다. 기본 제공 JSON 포맷터가 제거되고 XML 포맷터를 사용할 수 있는 경우, XML 포맷터가 string 반환 형식의 형식을 지정합니다. 그렇지 않으면 string 반환 형식이 406 Not Acceptable을 반환합니다.

HttpNoContentOutputFormatter가 없으면 null 개체는 구성된 포맷터를 사용하여 서식이 지정됩니다. 예시:

  • JSON 포맷터는 null의 본문이 포함된 응답을 반환합니다.
  • XML 포맷터는 xsi:nil="true"로 설정된 특성을 사용하여 빈 XML 요소를 반환합니다.

응답 형식 URL 매핑

클라이언트는 URL의 일부로 특정 형식을 요청할 수 있습니다. 예를 들면 다음과 같습니다.

  • 쿼리 문자열 또는 경로의 부분에서.
  • .Xml 또는 .json과 같은 서식 지정 파일 확장명을 사용하여.

요청 경로의 매핑은 API가 사용하는 경로에 지정해야 합니다. 예시:

[Route("api/[controller]")]
[ApiController]
[FormatFilter]
public class ProductsController : ControllerBase
{
    [HttpGet("{id}.{format?}")]
    public Product Get(int id)
    {

위 경로를 사용하면 요청된 형식을 선택적 파일 확장명으로 지정할 수 있습니다. [FormatFilter] 특성은 RouteData에서 형식 값의 존재 여부를 검사하며, 응답이 생성될 때 응답 형식을 적절한 포맷터에 매핑합니다.

경로 포맷터
/api/products/5 기본 출력 포맷터
/api/products/5.json JSON 포맷터(구성된 경우)
/api/products/5.xml XML 포맷터(구성된 경우)

ASP.NET Core MVC는 지정된 형식을 사용하거나 클라이언트의 요청에 대한 응답으로 응답 데이터의 서식 지정을 지원합니다.

형식별 작업 결과

일부 작업 결과 형식은 JsonResultContentResult와 같이 특정 형식과 관련됩니다. 작업은 다른 형식에 대한 클라이언트의 요청을 무시하고 항상 지정된 형식을 사용하는 결과를 반환할 수 있습니다. 예를 들어 JsonResult 반환은 JSON 형식의 데이터를 반환하고 ContentResult 반환은 일반 텍스트 형식 문자열 데이터를 반환합니다.

특정 형식을 반환하는 작업은 필요하지 않습니다. ASP.NET Core는 모든 개체 반환 값을 지원합니다. IActionResult 형식이 아닌 개체를 반환하는 작업의 결과는 적절한 IOutputFormatter 구현을 사용하여 직렬화됩니다. 자세한 내용은 ASP.NET Core 웹 API의 컨트롤러 작업 반환 형식을 참조하세요.

기본적으로 기본 제공 도우미 메서드 ControllerBase.Ok는 JSON 형식 데이터를 반환합니다.

[HttpGet]
public IActionResult Get()
    => Ok(_todoItemStore.GetList());

샘플 코드는 할 일 항목의 목록을 반환합니다. F12 브라우저 개발자 도구 또는 이전 코드와 함께 http-repl 을 사용하면 다음이 표시됩니다.

  • content-type:application/json; charset=utf-8을 포함하는 응답 헤더.
  • 요청 헤더입니다. 예를 들어 Accept 헤더가 있습니다. Accept 헤더는 앞의 코드에서 무시됩니다.

서식 있는 일반 텍스트 데이터를 반환하려면 ContentResultContent 도우미를 사용합니다.

[HttpGet("Version")]
public ContentResult GetVersion()
    => Content("v1.0.0");

위의 코드에서 반환된 Content-Typetext/plain입니다.

반환 형식이 여러 개인 작업의 경우 IActionResult를 반환합니다. 예를 들어 작업의 결과에 따라 서로 다른 HTTP 상태 코드를 반환하는 경우입니다.

콘텐츠 협상

콘텐츠 협상은 클라이언트가 헤더 수락을 지정하는 경우 발생합니다. ASP.NET Core에서 사용하는 기본 형식은 JSON입니다. 콘텐츠 협상은 다음과 같은 특징을 가집니다.

  • ObjectResult에 의해 구현됩니다.
  • 도우미 메서드에서 반환된 상태 코드별 작업 결과 상태 코드에 기본적으로 제공됩니다. 작업 결과 도우미 메서드는 ObjectResult를 기반으로 합니다.

모델 형식이 반환되는 경우 반환 형식은 ObjectResult입니다.

다음 작업 메서드는 OkNotFound 도우미 메서드를 사용합니다.

[HttpGet("{id:long}")]
public IActionResult GetById(long id)
{
    var todo = _todoItemStore.GetById(id);

    if (todo is null)
    {
        return NotFound();
    }

    return Ok(todo);
}

기본적으로 ASP.NET Core는 다음 미디어 유형을 지원합니다.

  • application/json
  • text/json
  • text/plain

Fiddler 또는 http-repl과 같은 도구는 요청 헤더를 Accept 설정하여 반환 형식을 지정할 수 있습니다. Accept 헤더에 서버가 지원하는 형식이 포함되어 있으면 해당 형식이 반환됩니다. 다음 섹션에서는 추가적인 포맷터를 추가하는 방법을 보여줍니다.

컨트롤러 작업은 POCO(Plain Old CLR Objects)를 반환할 수 있습니다. POCO가 반환되면 런타임에서는 개체를 래핑하는ObjectResult를 자동으로 만듭니다. 클라이언트는 형식이 지정된 직렬화된 개체를 가져옵니다. 반환되는 개체가 null이면 204 No Content 응답이 반환됩니다.

다음 예제에서는 개체 형식을 반환합니다.

[HttpGet("{id:long}")]
public TodoItem? GetById(long id)
    => _todoItemStore.GetById(id);

앞의 코드에서 유효한 할 일 항목에 대한 요청은 200 OK 응답을 반환합니다. 잘못된 할 일 항목에 대한 요청은 204 No Content 응답을 반환합니다.

Accept 헤더

콘텐츠 협상Accept 헤더가 요청에 나타나는 경우에 발생합니다. 요청에 Accept 헤더가 포함되어 있으면 ASP.NET Core는 다음을 수행합니다.

  • 기본 설정 순서에 따라 Accept 헤더의 미디어 형식을 열거합니다.
  • 지정된 형식 중 하나로 응답을 생성할 수 있는 포맷터를 찾으려고 시도합니다.

클라이언트의 요청을 충족할 수 있는 포맷터가 없는 경우 ASP.NET Core는 다음을 수행합니다.

  • MvcOptions.ReturnHttpNotAcceptabletrue로 설정된 경우 406 Not Acceptable을 반환합니다. 또는
  • 응답을 생성할 수 있는 첫 번째 포맷터를 찾으려고 시도합니다.

요청된 형식에 대해 포맷터가 구성되지 않은 경우에는 개체의 서식을 지정할 수 있는 첫 번째 포맷터가 사용됩니다. 요청에 Accept 헤더가 표시되지 않을 경우 다음이 수행됩니다.

  • 개체를 처리할 수 있는 첫 번째 포맷터는 응답을 직렬화하는 데 사용됩니다.
  • 발생하는 협상이 없습니다. 서버에서 반환할 형식을 결정합니다.

Accept 헤더에 */*가 포함되는 경우, RespectBrowserAcceptHeaderMvcOptions에서 true로 설정되지 않으면 헤더는 무시됩니다.

브라우저 및 콘텐츠 협상

일반적인 API 클라이언트와 달리 웹 브라우저는 Accept 헤더를 제공합니다. 웹 브라우저는 와일드카드를 비롯한 다양한 형식을 지정합니다. 기본적으로 프레임워크가 브라우저에서 요청이 수신되는 것을 감지할 경우 다음이 수행됩니다.

  • Accept 헤더는 무시됩니다.
  • 달리 구성되지 않은 경우 콘텐츠가 JSON에 반환됩니다.

이 접근 방식은 API를 소비할 때 브라우저에서 보다 일관된 환경을 제공합니다.

브라우저 허용 헤더를 준수하도록 앱을 구성하려면 RespectBrowserAcceptHeader 속성을 true로 설정합니다.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers(options =>
{
    options.RespectBrowserAcceptHeader = true;
});

포맷터 구성

추가 형식을 지원해야 하는 앱은 적절한 NuGet 패키지를 추가하고 지원을 구성할 수 있습니다. 입력 및 출력에 대한 개별 포맷터가 있습니다. 입력 포맷터는 모델 바인딩에서 사용됩니다. 출력 포맷터는 응답의 형식을 지정하는 데 사용됩니다. 사용자 지정 포맷터 생성에 대한 정보는 사용자 지정 포맷터를 참조하세요.

XML 형식 지원 추가

XmlSerializer를 사용하여 구현된 XML 포맷터를 구성하려면 AddXmlSerializerFormatters를 호출합니다.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers()
    .AddXmlSerializerFormatters();

위의 코드를 사용할 때 컨트롤러 메서드는 요청의 Accept 헤더에 따라 적절한 형식을 반환합니다.

System.Text.Json 기반 포맷터 구성

System.Text.Json 기반 포맷터에 대한 기능을 구성하려면 Microsoft.AspNetCore.Mvc.JsonOptions.JsonSerializerOptions를 사용합니다. 다음 강조 표시된 코드는 기본 camelCase 서식 대신 PascalCase 서식을 구성합니다.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers()
    .AddJsonOptions(options =>
    {
        options.JsonSerializerOptions.PropertyNamingPolicy = null;
    });

특정 작업에 대한 출력 serialization 옵션을 구성하려면 JsonResult를 사용합니다. 예시:

[HttpGet]
public IActionResult Get() 
    => new JsonResult(
        _todoItemStore.GetList(),
        new JsonSerializerOptions { PropertyNamingPolicy = null });

Newtonsoft.Json 기반 JSON 형식 지원 추가

기본 JSON 포맷터는 System.Text.Json을 사용합니다. Newtonsoft.Json 기반 포맷터를 사용하려면 Microsoft.AspNetCore.Mvc.NewtonsoftJson NuGet 패키지를 설치하고 Program.cs에서 구성합니다.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers()
    .AddNewtonsoftJson();

위의 코드에서 AddNewtonsoftJson에 대한 호출은 Newtonsoft.Json을 사용하도록 다음 Web API, MVC 및 Razor Pages 기능을 구성합니다.

일부 기능은 System.Text.Json 기반 포맷터와 잘 호환되지 않고 Newtonsoft.Json 기반 포맷터에 대한 참조를 필요로 할 수 있습니다. 앱이 다음과 같은 경우 Newtonsoft.Json 기반 포맷터를 계속해서 사용합니다.

  • Newtonsoft.Json 속성을 사용합니다. 예를 들어 [JsonProperty] 또는 [JsonIgnore]입니다.
  • 직렬화 설정을 사용자 지정합니다.
  • Newtonsoft.Json은 제공하는 기능에 의존합니다.

Newtonsoft.Json 기반 포맷터에 대한 기능을 구성하려면 SerializerSettings를 사용합니다.

builder.Services.AddControllers()
    .AddNewtonsoftJson(options =>
    {
        options.SerializerSettings.ContractResolver = new DefaultContractResolver();
    });

특정 작업에 대한 출력 serialization 옵션을 구성하려면 JsonResult를 사용합니다. 예시:

[HttpGet]
public IActionResult GetNewtonsoftJson()
    => new JsonResult(
        _todoItemStore.GetList(),
        new JsonSerializerSettings { ContractResolver = new DefaultContractResolver() });

ProblemDetailsValidationProblemDetails 응답 형식 지정

다음 작업 메서드는 응답을 만들기 위해 호출 ControllerBase.Problem 합니다.ProblemDetails

[HttpGet("Error")]
public IActionResult GetError()
    => Problem("Something went wrong.");

앱이 형식을 PascalCase로 설정하더라도 ProblemDetails 응답은 항상 camelCase입니다. ProblemDetails는 소문자를 지정하는 RFC 7807을 따릅니다.

[ApiController] 특성이 컨트롤러 클래스에 적용되면 컨트롤러는 모델 유효성 검사에 실패할 때 ValidationProblemDetails 응답을 만듭니다. 이 응답에는 모델의 속성 이름을 변경되지 않은 오류 키로 사용하는 사전이 포함됩니다. 예를 들어 다음 모델에는 유효성 검사가 필요한 단일 속성이 포함됩니다.

public class SampleModel
{
    [Range(1, 10)]
    public int Value { get; set; }
}

기본적으로 Value 속성이 잘못된 경우 반환되는 ValidationProblemDetails 응답은 다음 예제와 같이 Value의 오류 키를 사용합니다.

{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "traceId": "00-00000000000000000000000000000000-000000000000000-00",
  "errors": {
    "Value": [
      "The field Value must be between 1 and 10."
    ]
  }
}

오류 키로 사용되는 속성 이름의 형식을 지정하려면 IMetadataDetailsProvider의 구현을 MvcOptions.ModelMetadataDetailsProviders 컬렉션에 추가합니다. 다음 예제에서는 기본적으로 속성 이름을 camelCase로 형식을 지정하는 System.Text.Json 기반 구현인 SystemTextJsonValidationMetadataProvider를 추가합니다.

builder.Services.AddControllers();

builder.Services.Configure<MvcOptions>(options =>
{
    options.ModelMetadataDetailsProviders.Add(
        new SystemTextJsonValidationMetadataProvider());
});

SystemTextJsonValidationMetadataProvider는 속성 이름 형식 지정을 위한 사용자 지정 명명 정책을 지정하는 생성자에서 JsonNamingPolicy의 구현도 허용합니다.

모델 내의 속성에 대한 사용자 지정 이름을 설정하려면 속성에서 [JsonPropertyName] 특성을 사용합니다.

public class SampleModel
{
    [Range(1, 10)]
    [JsonPropertyName("sampleValue")]
    public int Value { get; set; }
}

Value 속성이 잘못된 경우 이전 모델에 대해 반환된 ValidationProblemDetails 응답은 다음 예제와 같이 sampleValue의 오류 키를 사용합니다.

{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "traceId": "00-00000000000000000000000000000000-000000000000000-00",
  "errors": {
    "sampleValue": [
      "The field Value must be between 1 and 10."
    ]
  }
}

Newtonsoft.Json을 사용하여 ValidationProblemDetails 응답의 형식을 지정하려면 NewtonsoftJsonValidationMetadataProvider를 사용합니다.

builder.Services.AddControllers()
    .AddNewtonsoftJson();

builder.Services.Configure<MvcOptions>(options =>
{
    options.ModelMetadataDetailsProviders.Add(
        new NewtonsoftJsonValidationMetadataProvider());
});

기본적으로 NewtonsoftJsonValidationMetadataProvider는 속성 이름을 camelCase로 형식을 지정합니다. NewtonsoftJsonValidationMetadataProvider는 속성 이름 형식 지정을 위한 사용자 지정 명명 정책을 지정하는 생성자에서 NamingPolicy의 구현도 허용합니다. 모델 내의 속성에 대한 사용자 지정 이름을 설정하려면 [JsonProperty] 특성을 사용합니다.

형식 지정

응답 형식을 제한하려면 [Produces] 필터를 적용합니다. 대부분 필터와 마찬가지로, [Produces]는 작업, 컨트롤러 또는 전역 범위에 적용할 수 있습니다.

[ApiController]
[Route("api/[controller]")]
[Produces("application/json")]
public class TodoItemsController : ControllerBase

위의 [Produces] 필터:

  • 컨트롤러 내의 모든 작업이 POCO(일반 이전 CLR 개체) 또는 ObjectResult 파생 형식에 대한 JSON 형식 응답을 반환하도록 합니다.
  • 다른 포맷터가 구성되고 클라이언트가 다른 형식을 지정하는 경우에도 JSON 형식 응답을 반환합니다.

자세한 내용은 필터를 참조하세요.

특수한 사례 포맷터

일부 특수한 경우 기본 제공 포맷터를 사용하여 구현됩니다. 기본적으로 string 반환 형식은 text/plain(Accept 헤더를 통해 요청된 경우 text/html)으로 형식이 지정됩니다. 이 동작은 StringOutputFormatter를 제거하여 삭제할 수 있습니다. 포맷터는 Program.cs에서 제거됩니다. 모델 개체 반환 형식이 있는 작업은 null을 반환하는 경우 204 No Content를 반환합니다. 이 동작은 HttpNoContentOutputFormatter를 제거하여 삭제할 수 있습니다. 다음 코드를 StringOutputFormatterHttpNoContentOutputFormatter를 제거합니다.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers(options =>
{
    // using Microsoft.AspNetCore.Mvc.Formatters;
    options.OutputFormatters.RemoveType<StringOutputFormatter>();
    options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
});

StringOutputFormatter가 없으면 기본 제공 JSON 포맷터가 string 반환 형식의 형식을 지정합니다. 기본 제공 JSON 포맷터가 제거되고 XML 포맷터를 사용할 수 있는 경우, XML 포맷터가 string 반환 형식의 형식을 지정합니다. 그렇지 않으면 string 반환 형식이 406 Not Acceptable을 반환합니다.

HttpNoContentOutputFormatter가 없으면 null 개체는 구성된 포맷터를 사용하여 서식이 지정됩니다. 예시:

  • JSON 포맷터는 null의 본문이 포함된 응답을 반환합니다.
  • XML 포맷터는 xsi:nil="true"로 설정된 특성을 사용하여 빈 XML 요소를 반환합니다.

응답 형식 URL 매핑

클라이언트는 URL의 일부로 특정 형식을 요청할 수 있습니다. 예를 들면 다음과 같습니다.

  • 쿼리 문자열 또는 경로의 부분에서.
  • .Xml 또는 .json과 같은 서식 지정 파일 확장명을 사용하여.

요청 경로의 매핑은 API가 사용하는 경로에 지정해야 합니다. 예시:

[ApiController]
[Route("api/[controller]")]
[FormatFilter]
public class TodoItemsController : ControllerBase
{
    private readonly TodoItemStore _todoItemStore;

    public TodoItemsController(TodoItemStore todoItemStore)
        => _todoItemStore = todoItemStore;

    [HttpGet("{id:long}.{format?}")]
    public TodoItem? GetById(long id)
        => _todoItemStore.GetById(id);

위 경로를 사용하면 요청된 형식을 선택적 파일 확장명을 사용하여 지정할 수 있습니다. [FormatFilter] 특성은 RouteData에서 형식 값의 존재 여부를 검사하며, 응답이 생성될 때 응답 형식을 적절한 포맷터에 매핑합니다.

경로 포맷터
/api/todoitems/5 기본 출력 포맷터
/api/todoitems/5.json JSON 포맷터(구성된 경우)
/api/todoitems/5.xml XML 포맷터(구성된 경우)

다형 역직렬화

기본 제공 기능을 통해 제한적으로 다형 serialization을 제공할 수 있지만 deserialization은 전혀 지원되지 않습니다. deserialization을 수행하려면 사용자 지정 변환기가 필요합니다. 다형 역직렬화의 전체 샘플은 다형 역직렬화를 참조하세요.

추가 리소스