• 除了目标一致,其它完全不一样,不管是思路还是实现。 GraphQL是查询语言,APIJSON是JSON传输结构协议(也包括内容)。 用GraphQL就要学习一堆概念和语法,前端要后端要写一大堆schema才能用对应schema结构的特定格式来请求,正因为GraphQL格式特殊,整个后端都要重写。 而APIJSON只是一个简单的JSON对应协议,采用标准且通用的的JSON格式,只有少数几个简单的概念,没有所谓的语法,Request和Response的结构严格对应,支持任意组合任意嵌套任意内容,并且还能和原来的RESTful API无缝兼容,几乎无迁移成本。 可以试试 https://github.com/TommyLemon/APIJSON

  • 确实很复杂,概念就很多很绕了,schema,mutation,Subscription,Source Stream,Notation Conventions... 而且Request和Schema并不是严格对应,尤其是多层嵌套的时候,Schema内层对象得通过外部函数调用来获取。 字段关联居然要手动resolve,前端发的每个Request都必须在后端先有对应的Schema声明。 GraphQL并没有替代REST,而是在Web/Client到REST Sever中间用GraphQL Server做了个中间层,最后还是调REST API.

  • 你好,感谢你的关注。
    查询:
    GraphQL-半自动化,只有过滤字段实现了自动化,且字段需要手动resolve。
    APIJSON-完全自动化,任意结构任意内容,只要数据库里有。

    兼容性:
    GraphQL-GraphQL特定格式,只能用GraphQL Server,Client,Web全套。
    APIJSON-标准JSON格式,能用JSON的地方就能用APIJSON。

    为了公平起见,以下GraphQL的所有示例都出自官方文档及代码。

    1.查询条件
    GraphQL:

    table(key0:value0,key1:value1,...) {
    }
    
    {
      user(id: 4) {
        id
        name
      }
    }
    

    APIJSON:

    Table: {
        key0:value0,
        key1:value1,
        ...
    }
    
    {
        "User":{
            "id":38710
        }
    }
    

    2.返回字段
    GraphQL:
    只返回已声明字段

    {
        key0
        key1
        ...
    }
    
    {
      user(id: 4) {
        id
        name
      }
    }
    

    APIJSON:
    默认返回全部,可加上以下条件限制

    "@column":"key0,key1,..."
    
    {
        "User":{
            "id":38710,
            "@column":"id,name"
        }
    }
    

    3.查询数组:
    GraphQL:
    需要后端在schema中手动resolve

    query noFragments {
      user(id: 4) {
        friends(first: 10) {
          id
          name
        }
      }
    }
    

    APIJSON:
    "[]":{} 自动解析

    {
        "[]":{
            "count":10,
            "User":{
            }
        }
    }
    

    4.关联查询:
    需要后端在schema中手动resolve关联
    GraphQL:

    query inlineFragmentTyping {
      profiles(handles: ["zuck", "cocacola"]) {
        handle
        ... on User {
          friends {
            count
          }
        }
        ... on Page {
          likers {
            count
          }
        }
      }
    }
    

    APIJSON:
    "key@":"key0/key1/.../targetKey" 自动解析

    {
        "[]": {
            "User": {
                "name$": ["Strong", "Mike"]
            },
            "Moment": {
                "userId@": "[]/User/id"
            }
        }
    }
    

    5.后端定义结构
    GraphQL:
    读、写操作都需要,代码中,且字段要手动resolve。
    Node.js

    var schema = new GraphQLSchema({
      query: new GraphQLObjectType({
        name: 'RootQueryType',
        fields: {
          hello: {
            type: GraphQLString,
            resolve() {
              return 'world';
            }
          }
        }
      })
    });
    

    Java

    GraphQLObjectType queryType = newObject()
                            .name("helloWorldQuery")
                            .field(newFieldDefinition()
                                    .type(GraphQLString)
                                    .name("hello")
                                    .staticValue("world"))
                            .build();
    
            GraphQLSchema schema = GraphQLSchema.newSchema()
                            .query(queryType)
                            .build();
    

    APIJSON:
    只有写操作才需要,自动解析自动校验,而且是在数据库Request表中定义,完全可视化。

    {
        "Moment":{
            "DISALLOW":"id",
            "NECESSARY":"userId,pictureList"
        }
    }
    

    6.前端查询灵活性
    GraphQL:
    1.所有结构都要后端先定义,前端/客户端才能按照已定义结构查询。
    2.多层嵌套需要后端在结构外声明内部结构,不够直观,Request和Response不能完全对应(Request少了内层结构)。

    后端定义:

    const UserType = new GraphQLType({
        name:'User",
        fields:{
            id:{
                type:GraphQLInt
            },
            name:{
                type:GraphQLString
            }
        }
    })
    
    const CommentType = new GraphQLType({
        name:'Comment",
        fields:{
            id:{
                type:GraphQLInt
            },
            toId:{
                type:GraphQLInt
            },
            userId:{
                type:GraphQLInt
            },
            content:{
                type:GraphQLString
            }
        }
    })
    
    
    const MomentType = new GraphQLType({
        name:'Moment",
        fields:{
            id:{
                type:GraphQLInt
            },
            userId:{
                type:GraphQLInt
            },
            title:{
                type:GraphQLString
            },
            content:{
                type:GraphQLString
            },
            user:{
                type:new GraphQLObject(UserType)
                resolve:(moment) => getUserById(userId)
            },
            comments:{
               type:new GraphQLList(CommentType),
               resolve:(moment) => moment.commentIds.map(id => getCommentById(id))
            }
        }
    })
    
    
    function getUserById(id) {
        //查询User...
        return new UserType(id) //这里只是模拟,实际代码一般会比较多
    }
    
    function getCommentById(id) {
        //查询Comment...
        return new CommentType(id) //这里只是模拟,实际代码一般会比较多
    }
    

    前端请求:

    query momentFragmentTyping {
         moments(first: 10, text: "a") {
                id
                userId
                title
                content
                user {
                    id
                    name
                }
                comments(first: 2) {
                        id
                        toId
                        userId
                        content
                }
         }
    })
    

    注:实在找不到官方的,群里问出了这个。

    APIJSON:
    1)不需要后端定义,只要 类声明+权限注解+权限注册 3行代码配置Model允许的操作及对应的角色。
    3)可任意组合、任意嵌套,Request和Response完全对应。

    后端定义:

    //注册表并添加权限,以下都用默认
    @MethodAccess
    public class User {
    }
    
    @MethodAccess
    public class Comment {
    }
    
    @MethodAccess
    public class Moment {
    }
    
    //AccessVerifier内添加权限
    accessMap.put(User.class.getSimpleName(), getAccessMap(User.class.getAnnotation(MethodAccess.class)));
    accessMap.put(Moment.class.getSimpleName(), getAccessMap(Moment.class.getAnnotation(MethodAccess.class)));
    accessMap.put(Comment.class.getSimpleName(), getAccessMap(Comment.class.getAnnotation(MethodAccess.class)));
    

    前端请求:

    {
      "[]":{                             //请求一个数组
        "page":0,                        //数组条件
        "count":2,
        "Moment":{                       //请求一个名为Moment的对象
          "content$":"%a%"               //对象条件,搜索content中包含a的动态
        },
        "User":{
          "id@":"/Moment/userId",        //缺省依赖路径,从所处容器的父容器路径开始
          "@column":"id,name,head"       //指定返回字段
        },
        "Comment[]":{                    //请求一个名为Comment的数组,并去除Comment包装
          "count":2,
          "Comment":{
            "momentId@":"[]/Moment/id"   //完整依赖路径
          }
        }
      }
    }
    

    7.前端写操作请求
    GraphQL:
    代码中定义mutation schema。

    mutation {
      likeStory(storyID: 12345) {
        story {
          likeCount
        }
      }
    }
    

    APIJSON:
    操作单条记录必传"id":Long,操作多条记录必传"id{}":[Long],还有自动化权限校验,保证安全性。

    {
        "Moment":{
            "id":12,
            "praiseUserIdList+":[
                38710
            ]
        }
    }
    

    等我有时间再发篇博文,做一个详细的比较。
    APIJSON目前有Java Server,Android,JavaScript 3种实现,如果要和GraphQL比,这几种语言随便挑。

    APIJSON在线测试
    http://39.108.143.172

    APIJSON项目主页
    https://github.com/TommyLemon/APIJSON

    欢迎使用、建议、吐槽、反馈 ^_^

付出终有回报