6
votes

La meilleure façon de définir un objet cartographique dans le schéma GraphQL?

J'essaie de mapper une chaîne clé avec des tableaux d'objets.

Je peux créer un objet simple mais je veux ajouter facilement un objet dans ces tableaux. L'objet Map est parfait pour ce faire.

Problème: Je ne sais pas comment définir la carte de type pour GraphQL: '(

@ObjectType()
export class Inventaire
  @Field()
  _id: string;

 @Field()
  stocks: Map<string, Article[]>;
}


1 commentaires

3 Réponses :


9
votes

GraphQL est un langage fortement typé et ne fournit aucun type de type de carte prêt à l'emploi. Un objet blob JSON de paires clé-valeur n'a pas de schéma fort, vous ne pouvez donc pas avoir quelque chose comme ceci:

    data [
    {
        key: foo1,
        value: { some Article Object}
    },
    {
        key: foo2,
        value: { some Article Object}
    },
    {
        key: foo3,
        value: { some Article Object}
    },
]

Cependant, vous pouvez définir un schéma GraphQL pour avoir un type de tuple clé-valeur, puis définir votre propriété pour renvoyer un tableau de ces tuples.

type articleMapTuple {
     key: String
     value: Article
}

type Inventaire {
     stocks: [articleMapTuple]
}

Ensuite, vos types de retour ressembleraient à ceci:

{
    key1: val1,
    key2: val2,
    key3: val3,
    ...
}


3 commentaires

"GraphQL est un langage fortement typé, et ne fournit aucun type de carte prêt à l'emploi." comme il n'y a pas de langues fortement typées qui fournissent le type de carte? Il n'y a aucun lien entre la première et la seconde moitié de la phrase.


Peut-être devrais-je clarifier - GraphQL est un langage fortement typé qui ne fournit aucun type de carte prêt à l'emploi. Par conséquent, vous devez définir le vôtre.


@gacharya l'absence de type Map n'a toujours rien à voir avec un typage fort. Les cartes sont utiles pour représenter des données qui sont intrinsèquement un mappage. S'il est utilisé pour représenter les propriétés d'un objet, c'est assez mauvais et va à l'encontre du but de la saisie, mais ce n'est pas l'objectif principal des cartes.



0
votes

Vous pouvez utiliser ce package https://www.npmjs.com/package/graphql-type-json .

Exemple:

import { makeExecutableSchema } from 'graphql-tools';
import GraphQLJSON, { GraphQLJSONObject } from 'graphql-type-json';
 
const typeDefs = `
scalar JSON
scalar JSONObject
 
type MyType {
  myValue: JSON
  myObject: JSONObject
}
 
# ...
`;
 
const resolvers = {
  JSON: GraphQLJSON,
  JSONObject: GraphQLJSONObject,
};
 
export default makeExecutableSchema({ typeDefs, resolvers });


0 commentaires

0
votes

GraphQL ne prend pas en charge nativement le type de carte. Vous pouvez créer votre propre scalaire pour Map ou utiliser ObjectScalar existant défini dans le repo https://github.com/graphql-java/graphql-java-extended-scalars

scalar Object

type Result {
 value : Object
}

import graphql.Assert;
import graphql.language.ArrayValue;
import graphql.language.BooleanValue;
import graphql.language.EnumValue;
import graphql.language.FloatValue;
import graphql.language.IntValue;
import graphql.language.NullValue;
import graphql.language.ObjectValue;
import graphql.language.StringValue;
import graphql.language.Value;
import graphql.language.VariableReference;
import graphql.language.ObjectField;
import graphql.scalars.util.Kit;
import graphql.schema.Coercing;
import graphql.schema.CoercingParseLiteralException;
import graphql.schema.CoercingParseValueException;
import graphql.schema.CoercingSerializeException;
import graphql.schema.GraphQLScalarType;
import org.springframework.stereotype.Component;

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Component
public class ObjectScalar extends GraphQLScalarType {
    public ObjectScalar() {
        this("Object", "An object scalar");
    }

    ObjectScalar(String name, String description) {
        super(name, description, new Coercing<Object, Object>() {
            public Object serialize(Object input) throws CoercingSerializeException {
                return input;
            }

            public Object parseValue(Object input) throws CoercingParseValueException {
                return input;
            }

            public Object parseLiteral(Object input) throws CoercingParseLiteralException {
                return this.parseLiteral(input, Collections.emptyMap());
            }

            public Object parseLiteral(Object input, Map<String, Object> variables)
                    throws CoercingParseLiteralException {
                if (!(input instanceof Value)) {
                    throw new CoercingParseLiteralException("Expected AST type 'StringValue' but" +
                            " was '" + Kit.typeName(input) + "'.");
                } else if (input instanceof NullValue) {
                    return null;
                } else if (input instanceof FloatValue) {
                    return ((FloatValue)input).getValue();
                } else if (input instanceof StringValue) {
                    return ((StringValue)input).getValue();
                } else if (input instanceof IntValue) {
                    return ((IntValue)input).getValue();
                } else if (input instanceof BooleanValue) {
                    return ((BooleanValue)input).isValue();
                } else if (input instanceof EnumValue) {
                    return ((EnumValue)input).getName();
                } else if (input instanceof VariableReference) {
                    String varName = ((VariableReference)input).getName();
                    return variables.get(varName);
                } else {
                    List values;
                    if (input instanceof ArrayValue) {
                        values = ((ArrayValue)input).getValues();
                        return values.stream().map((v) -> {
                            return this.parseLiteral(v, variables);
                        }).collect(Collectors.toList());
                    } else if (input instanceof ObjectValue) {
                        values = ((ObjectValue)input).getObjectFields();
                        Map<String, Object> parsedValues = new LinkedHashMap();
                        values.forEach((fld) -> {
                            Object parsedValue = this.parseLiteral(((ObjectField)fld).getValue(),
                                    variables);
                            parsedValues.put(((ObjectField)fld).getName(), parsedValue);
                        });
                        return parsedValues;
                    } else {
                        return Assert.assertShouldNeverHappen("We have covered all Value types",
                                new Object[0]);
                    }
                }
            }
        });
    }
}


0 commentaires