GraphQL - validation 검증

21968 단어 GraphQL
공식 문서

1. 개요


GraphQL은 요청이 문법적으로 올바른지 확인하는 것이 아니라 현재 서버의 GraphQL 모드 상하문에서 올바른지 확인합니다.검색이 유효한지 미리 판단하여 서버와 클라이언트가 유효하지 않은 검색을 만들 때 개발자에게 효과적으로 통지할 수 있도록 하고 실행할 때 알 필요가 없다.

유형 시스템 변천


GraphQL 형식 시스템 모드는 시간이 지날수록 새로운 형식과 필드를 추가합니다. 이전의 유효한 요청은 나중에 무효가 될 수 있습니다.이전에 유효한 요청이 무효가 될 수 있는 모든 변경 사항은 중대한 변경으로 간주됩니다.
다음 유형 시스템은 다음 예제에서 참조합니다.
enum DogCommand { SIT, DOWN, HEEL }

type Dog implements Pet {
  name: String!
  nickname: String
  barkVolume: Int
  doesKnowCommand(dogCommand: DogCommand!): Boolean!
  isHousetrained(atOtherHomes: Boolean): Boolean!
  owner: Human
}

interface Sentient {
  name: String!
}

interface Pet {
  name: String!
}

type Alien implements Sentient {
  name: String!
  homePlanet: String
}

type Human implements Sentient {
  name: String!
}

enum CatCommand { JUMP }

type Cat implements Pet {
  name: String!
  nickname: String
  doesKnowCommand(catCommand: CatCommand!): Boolean!
  meowVolume: Int
}

union CatOrDog = Cat | Dog
union DogOrHuman = Dog | Human
union HumanOrAlien = Human | Alien

type QueryRoot {
  dog: Dog
}

2. 상세 정보


2.1 운영 사양


2.1.1 작업은 이름을 바꿀 수 없으며 각 작업의 유형이 달라도 사용할 수 없습니다.

//  
query dogOperation {
  dog {
    name
  }
}
mutation dogOperation {
  mutateDog {
    id
  }
}

2.1.2 익명으로 조작하면 하나의 조작만 있을 수 있고 다른 조작은 할 수 없으며 이미 명명된 조작이라도 할 수 없다.

//  
query dogOperation {
  dog {
    name
  }
}
{
  mutateDog {
    id
  }
}

2.2 필드


2.2.1 객체, 인터페이스 및 결합 유형의 필드가 있을 때 선택 가능


연합이 필드를 정의하지 않기 때문에 필드는 메타 필드 __ 를 제외하고는 연합 유형 선택 세트에서 직접 선택할 수 없습니다.typename.연합 형식 선택 집합에서 나온 필드만 세그먼트를 통해 간접적으로 조회할 수 있습니다.
//  :
fragment inDirectFieldSelectionOnUnion on CatOrDog {
  __typename
  ... on Pet {
    name
  }
  ... on Dog {
    barkVolume
  }
}
//  :
fragment directFieldSelectionOnUnion on CatOrDog {
  name
  barkVolume
}

2.2.2 필드 선택 병합


실행 중 클라이언트가 같은 이름의 여러 필드를 보내면 실행할 필드와 파라미터, 결과 값이 명확해야 합니다.따라서 같은 대상이 만날 수 있는 두 필드의 선택은 같은 상황에서만 유효하다.
//  :
fragment mergeIdenticalFields on Dog {
  name
  name
}
fragment mergeIdenticalFieldsWithIdenticalArgs on Dog {
  doesKnowCommand(dogCommand: SIT)
  doesKnowCommand(dogCommand: SIT)
}
//  :
fragment conflictingBecauseAlias on Dog {
  name: nickname
  name
}

2.2.3 잎 필드


잎 필드는 필드의 선택을 허용하지 않는 표량입니다.반면 GraphQL 쿼리의 잎 필드는 반드시 눈금이어야 합니다.
//  :
fragment scalarSelectionsNotAllowedOnBoolean on Dog {
  barkVolume {
    sinceWhen
  }
}

2.3 Arguments 매개변수


매개 변수는 필드와 명령에 사용할 수 있습니다.

2.3.1 서비스 측이 필드나 명령의 가능한 매개 변수를 정의한 후에야 클라이언트가 사용할 수 있다

//  :
fragment argOnOptional on Dog {
  isHousetrained(atOtherHomes: true) @include(if: true)
}
//  ,  doesKnowCommand   command  。
fragment invalidArgName on Dog {
  doesKnowCommand(command: CLEAN_UP_HOUSE)
}
//  ,  @include   unless。
fragment invalidArgName on Dog {
  isHousetrained(atOtherHomes: true) @include(unless: false)
}

2.3.2 참수치 유형의 정확성

  • 매개 변수 값의 유형은 자동 변환 규칙을 만족시키는 것이 합법적이다.예를 들어 String 매개변수는 Int 유형을 사용할 수 있습니다.Int 유형은 Float 유형으로 강제 변환될 수 있지만 Float 유형은 Int 유형으로 변환할 수 없습니다
  • //  :
    fragment goodBooleanArg on Arguments {
      booleanArgField(booleanArg: true)
    }
    fragment coercedIntIntoFloatArg on Arguments {
      floatArgField(floatArg: 1)
    }
    //  ,Float   Int  :
    fragment stringIntoInt on Arguments {
      intArgField(intArg: "3")
    }
  • 비공 매개 변수는 반드시 전송해야 하며, 전송하지 않거나null을 전송하는 것은 모두 무효입니다..
  • //  :
    fragment missingRequiredArg on Arguments {
      notNullBooleanArgField(nonNullBooleanArg: null)
    }

    2.4 Fragments 세션


    세션은 이름을 바꿀 수 없으며, 정의된 후에 사용해야 합니다. 그렇지 않으면 검색이 잘못됩니다.수납장... 예를 들면...dogFragment .

    2.4.1 세션 선언


    세션 선언은 이름을 바꿀 수 없으며 Schema에 이미 있는 유형을 기반으로 해야 합니다on SomeType .
    //  :
    fragment inlineFragment on Dog {
      ... on Dog {
        name
      }
    }
    fragment inlineFragment2 on Dog {
      ... @include(if: true) {
        name
      }
    }
    //  :
    fragment notOnExistingType on NotInSchema {
      name
    }
    fragment inlineNotExistingType on Dog {
      ... on NotInSchema {
        name
      }
    }

    2.4.2 복합 유형의 단편


    내연 세그먼트든 일반 세그먼트든 UNION, INTERFACE 또는 OBJECT를 기반으로 해야 합니다.표량이나 잎에는 무효다.
    //  :
    fragment fragOnScalar on Int {
      something
    }
    
    fragment inlineFragOnScalar on Dog {
      ... on Boolean {
        somethingElse
      }
    }

    2.4.3 세션은 순환을 구성할 수 없습니다

    //  , :
    {
      dog {
        ...nameFragment
      }
    }
    
    fragment nameFragment on Dog {
      name
      ...barkVolumeFragment
    }
    
    fragment barkVolumeFragment on Dog {
      barkVolume
      ...nameFragment
    }

    2.4.4 조각은 중첩할 수 있다


    아래의 추상적인 범위는 인터페이스 인터페이스 또는 연합 유니온의 작용역을 가리키고, 대상 범위는 대상 Object의 작용역을 가리킨다.

    1. 객체 범위에서 중첩된 객체 세그먼트


    대상 유형의 범위 내에서 유일하게 유효한 대상 유형 부분은 바로 이 부분 자체이다.
    //  :
    query you{
      viewer {
        ...myFragment
      }
    }
    fragment myFragment on User{
        name
        ... on User { //   User,  User  。
            login
        }
    }
    //  :
    {
      "data": {
        "viewer": {
          "name": null,
          "login": "kikajack"
        }
      }
    }
    //  :
    fragment myFragment on User{
        name
        ... on Repositories{ //   User,  User  。
            id
        }
    }

    2. 대상 범위에 추상적인 부분을 삽입


    대상 유형의 범위 내에서 대상 유형이 인터페이스를 실현하거나 연합된 구성원이라면 연합 또는 인터페이스를 사용하여 전파할 수 있다.
    //  ,  Dog   Pet。
    fragment petNameFragment on Pet {
      name
    }
    fragment interfaceWithinObjectFragment on Dog {
      ...petNameFragment
    }
    //  ,  Dog   CatOrDog Union  
    fragment catOrDogNameFragment on CatOrDog {
      ... on Cat {
        meowVolume
      }
    }
    fragment unionWithObjectFragment on Dog {
      ...catOrDogNameFragment
    }

    3. 추상적인 범위에서 삽입된 대상의 단편


    대상 유형이 이 인터페이스나 연합의 가능한 유형 중 하나일 때만 대상 유형 세션의 상하문에서 연합이나 인터페이스를 사용하여 확장할 수 있습니다.
    // :
    fragment petFragment on Pet {
      name
      ... on Dog {
        barkVolume
      }
    }
    fragment catOrDogFragment on CatOrDog {
      ... on Cat {
        meowVolume
      }
    }

    4. 추상적인 범위에 추상적인 부분을 삽입한다


    Union과 Interface 세션은 서로 중첩될 수 있습니다.역할 영역과 확장 가능한 유형의 교차에 최소한 하나의 대상 유형이 존재하면 유효합니다.
    //  , , DogOrHuman 。
    fragment unionWithInterface on Pet {
      ...dogOrHumanFragment
    }
    fragment dogOrHumanFragment on DogOrHuman {
      ... on Dog {
        barkVolume
      }
    }
    //  , Pet Sentient 。
    fragment nonIntersectingInterfaces on Pet {
      ...sentientFragment
    }
    fragment sentientFragment on Sentient {
      name
    }

    2.5 Values 값


    Values의 고유성은 다음 질의에서 검증되지 않습니다.
    {
      field(arg: { field: true, field: false })
    }

    2.6 Directives 명령


    2.6.1 명령은 유효한 위치에서만 사용할 수 있습니다.


    다음 검색은 검증을 통과하지 못합니다. QUERY가 @skip 명령을 인정하지 않기 때문에 @skip의 유효한 위치가 아닙니다.
    query @skip(if: $foo) {
      field
    }

    2.6.2


    각 위치에서는 명령을 반복할 수 없습니다.다음 질의는 검증되지 않습니다.
    query ($foo: Boolean = true, $bar: Boolean = false) {
      field @skip(if: $foo) @skip(if: $bar)
    }

    2.7 Variables 변수


    2.7.1 변수 기본값


    변수가 비어 있지 않으면 기본값을 정의할 수 있습니다.변수가 비어 있지 않으면 기본값은 액세스할 수 없습니다.

    //  
    query houseTrainedQuery($atOtherHomes: Boolean = true) {
      dog {
        isHousetrained(atOtherHomes: $atOtherHomes)
      }
    }
    //  :
    query houseTrainedQuery($atOtherHomes: Boolean! = true) {
      dog {
        isHousetrained(atOtherHomes: $atOtherHomes)
      }
    }

    기본값은 변수 유형과 호환되어야 합니다.형식이 일치해야 하거나 강제 형식이어야 합니다.

    //  :
    query houseTrainedQuery($atOtherHomes: Boolean = "true") {
      dog {
        isHousetrained(atOtherHomes: $atOtherHomes)
      }
    }
    //  , 。
    query intToFloatQuery($floatVar: Float = 1) {
      arguments {
        floatArgField(floatArg: $floatVar)
      }
    }

    2.7.2 입력 유형의 변수


    변수는 유형을 입력할 때 표량, 열거, 입력 대상, 목록 및 이 유형의 비공변체만 사용할 수 있습니다.대상, 연합, 인터페이스가 될 수 없습니다.
    이러한 예제에 대해 다음 유형을 추가합니다.
    input ComplexInput { name: String, owner: String }
    extend type QueryRoot {
      findDog(complex: ComplexInput): Dog
      booleanList(booleanListArg: [Boolean!]): Boolean
    }
    //  :
    query takesBoolean($atOtherHomes: Boolean) {
      dog {
        isHousetrained(atOtherHomes: $atOtherHomes)
      }
    }
    query takesComplexInput($complexInput: ComplexInput) {
      findDog(complex: $complexInput) {
        name
      }
    }
    query TakesListOfBooleanBang($booleans: [Boolean!]) {
      booleanList(booleanListArg: $booleans)
    }
    //  :
    query takesCat($cat: Cat) {
      # ...
    }
    query takesDogBang($dog: Dog!) {
      # ...
    }
    query takesListOfPet($pets: [Pet]) {
      # ...
    }
    query takesCatOrDog($catOrDog: CatOrDog) {
      # ...
    }

    2.7.3 변수는 작업의 맨 위에 정의된 후에야 사용할 수 있다


    변수 범위는 조작에 기초하고 조작의 상하문에서 사용하는 변수는 반드시 조작의 맨 위에 정의되어야 한다.

    //  :
    query variableIsDefined($atOtherHomes: Boolean) {
      dog {
        isHousetrained(atOtherHomes: $atOtherHomes)
      }
    }
    //  :
    query variableIsNotDefined {
      dog {
        isHousetrained(atOtherHomes: $atOtherHomes)
      }
    }

    조각 Fragment는 작업 맨 위에 정의된 변수를 직접 사용할 수 있습니다. Fragment에서 사용하는 변수는 모든 작업에 정의되어야 합니다.

    //  :
    query variableIsDefinedUsedInSingleFragment($atOtherHomes: Boolean) {
      dog {
        ...isHousetrainedFragment
      }
    }
    fragment isHousetrainedFragment on Dog {
      isHousetrained(atOtherHomes: $atOtherHomes)
    }
    //  :
    query housetrainedQueryOne($atOtherHomes: Boolean) {
      dog {
        ...isHousetrainedFragment
      }
    }
    query housetrainedQueryTwoNotDefined {
      dog {
        ...isHousetrainedFragment
      }
    }
    fragment isHousetrainedFragment on Dog {
      isHousetrained(atOtherHomes: $atOtherHomes)
    }

    2.7.4 변수 정의 후 반드시 사용


    조작에 의해 정의된 모든 변수는 이 조작이나 이 조작에서 전달된 부분에서 사용하거나 이 조작에서 전달된 부분에서 사용해야 한다.사용하지 않은 변수는 검증 오류를 초래할 수 있습니다.
    //  ,  $atOtherHomes   isHousetrainedFragment  ,  variableUsedInFragment。
    query variableUsedInFragment($atOtherHomes: Boolean) {
      dog {
        ...isHousetrainedFragment
      }
    }
    fragment isHousetrainedFragment on Dog {
      isHousetrained(atOtherHomes: $atOtherHomes)
    }
    //  , $ atOtherHomes:
    query variableNotUsedWithinFragment($atOtherHomes: Boolean) {
      ...isHousetrainedWithoutVariableFragment
    }
    fragment isHousetrainedWithoutVariableFragment on Dog {
      isHousetrained
    }

    2.7.5 변수는 전송된 매개 변수와 호환되어야 합니다


    유형이 일치하지 않으므로 다음 예는 실패합니다.

    query intCannotGoIntoBoolean($intArg: Int) {
      arguments {
        booleanArgField(booleanArg: $intArg)
      }
    }

    비어 있는 변수는 비어 있지 않은 매개 변수에 전달될 수 없습니다 (기본 매개 변수를 제공할 때)

    query booleanArgQuery($booleanArg: Boolean) {
      arguments {
        nonNullBooleanArgField(nonNullBooleanArg: $booleanArg)
      }
    }

    목록 형식에 대해 빈 목록을 비빈 목록에 전달할 수 없으며,null 값의 목록을 비빈 값의 목록에 전달할 수 없습니다

    //  :
    query nonNullListToList($nonNullBooleanList: [Boolean]!) {
      arguments {
        booleanListArgField(booleanListArg: $nonNullBooleanList)
      }
    }
    //  , :
    query listToNonNullList($booleanList: [Boolean]) {
      arguments {
        nonNullBooleanListField(nonNullBooleanListArg: $booleanList)
      }
    }

    좋은 웹페이지 즐겨찾기