在SAS宏中解析JSON对象

在SAS宏中解析JSON对象,json,sas,sas-macro,groovy,Json,Sas,Sas Macro,Groovy,这里是输入JSON文件。它必须在SAS数据集中进行解析 "results": [ { "acct_nbr": 1234, "firstName": "John", "lastName": "Smith", "age": 25, "address": { "streetAddress": "21 2nd Street", "city": "New York", "state": "NY", "

这里是输入JSON文件。它必须在SAS数据集中进行解析

"results":
[
 {
    "acct_nbr": 1234,
    "firstName": "John",
    "lastName": "Smith",
    "age": 25,
    "address": {
        "streetAddress": "21 2nd Street",
        "city": "New York",
        "state": "NY",
        "postalCode": "10021"
        }
 }
,
{
    "acct_nbr": 3456,
    "firstName": "Sam",
    "lastName": "Jones",
    "age": 32,
    "address": {
        "streetAddress": "25 2nd Street",
        "city": "New Jersy",
        "state": "NJ",
        "postalCode": "10081"
        }
 }
]
我希望SAS数据集中的唯一地址字段的输出如下:

ACCT_NBR    FIELD_NAME  FIELD_VALUE
1234    streetAddress   21 2nd Street
1234    city    New York
1234    state   NY
1234    postalCode  10021
3456    streetAddress   25 2nd Street
3456    city    New Jersy
3456    state   NJ
3456    postalCode  10081
我尝试了不同的方法,但没有类似的输出。 甚至试过从。。。但无法获得所需的输出

这是我的代码……和输出

LIBNAME src  '/home/user/read_JSON';

filename data '/home/user/read_JSON/test2.json';
data src.testdata2;
    infile data lrecl = 32000 truncover scanover;
        input @'"streetAddress": "' streetAddress $255. @'"city": "' city $255. @'"state": "' state $2. @'"postalCode": "' postalCode $255.;
        streetAddress = substr(streetAddress,1,index(streetAddress,'",')-2);
        city = substr( city,1,index( city,'",')-2);
        state = substr(state,1,index(state,'",')-2);
        postalCode = substr(postalCode,1,index(postalCode,'",')-2);
run;

proc print data=src.testdata2;
RUN;
我在.lst文件中的输出

假设您了解groovy,那么可以很容易地使用ProcGroovy解析JSON。对Twitter进行身份验证时,展示了如何进行身份验证的详细示例;以下是一些亮点

这假设您拥有Groovy JAR文件和输出示例使用的文件的方法

下面是我的尝试;我觉得它不太管用,但我也不懂Groovy。一般概念应该是正确的。如果您想尝试这种方法,但无法了解其中的细节,您可以重新标记您的问题,或使用该标记提出新问题

%let groovydir=C:\Program Files\SASHome_9.4\SASFoundation\9.4\groovy; *the location the groovy JARs are located at;

%let sourcefile=c:\temp\json.txt;
%let outfile=c:\temp\json.csv;

proc groovy classpath="&groovydir.\groovy-all-2.2.0.jar;&groovydir.\opencsv-2.3.jar"; 

   submit "&sourcefile" "&outfile"; 
      import groovy.json.*
      import au.com.bytecode.opencsv.CSVWriter

      def input = new File(args[0]).text
      def output = new JsonSlurper().parseText(input)
      def csvoutput = new FileWriter(args[1])

      CSVWriter writer = new CSVWriter(csvoutput);

      String[] header = new String[8];
      header[0] = "results.acct_nbr";
      header[1] = "results.firstName";
      header[2] = "results.lastName";
      header[3] = "results.age";
      header[4] = "results.address.streetAddress";
      header[5] = "results.address.city";
      header[6] = "results.address.state";
      header[7] = "results.address.postalCode";
      writer.writeNext(header);

      output.statuses.each {
         String[] content = new String[8];
         content[0] = it.results.acct_nbr.toString();
         content[1] = it.results.firstName.toString();
         content[2] = it.results.lastName.toString();
         content[3] = it.results.age.toString();
         content[4] = it.results.address.streetAddress.toString();
         content[5] = it.results.address.city.toString();
         content[6] = it.results.address.state.toString();
         content[7] = it.results.address.postalCode.toString(); 
         writer.writeNext(content)
      }         

      writer.close();

    endsubmit; 
 quit;
假设您了解groovy,那么可以很容易地使用ProcGroovy解析JSON。对Twitter进行身份验证时,展示了如何进行身份验证的详细示例;以下是一些亮点

这假设您拥有Groovy JAR文件和输出示例使用的文件的方法

下面是我的尝试;我觉得它不太管用,但我也不懂Groovy。一般概念应该是正确的。如果您想尝试这种方法,但无法了解其中的细节,您可以重新标记您的问题,或使用该标记提出新问题

%let groovydir=C:\Program Files\SASHome_9.4\SASFoundation\9.4\groovy; *the location the groovy JARs are located at;

%let sourcefile=c:\temp\json.txt;
%let outfile=c:\temp\json.csv;

proc groovy classpath="&groovydir.\groovy-all-2.2.0.jar;&groovydir.\opencsv-2.3.jar"; 

   submit "&sourcefile" "&outfile"; 
      import groovy.json.*
      import au.com.bytecode.opencsv.CSVWriter

      def input = new File(args[0]).text
      def output = new JsonSlurper().parseText(input)
      def csvoutput = new FileWriter(args[1])

      CSVWriter writer = new CSVWriter(csvoutput);

      String[] header = new String[8];
      header[0] = "results.acct_nbr";
      header[1] = "results.firstName";
      header[2] = "results.lastName";
      header[3] = "results.age";
      header[4] = "results.address.streetAddress";
      header[5] = "results.address.city";
      header[6] = "results.address.state";
      header[7] = "results.address.postalCode";
      writer.writeNext(header);

      output.statuses.each {
         String[] content = new String[8];
         content[0] = it.results.acct_nbr.toString();
         content[1] = it.results.firstName.toString();
         content[2] = it.results.lastName.toString();
         content[3] = it.results.age.toString();
         content[4] = it.results.address.streetAddress.toString();
         content[5] = it.results.address.city.toString();
         content[6] = it.results.address.state.toString();
         content[7] = it.results.address.postalCode.toString(); 
         writer.writeNext(content)
      }         

      writer.close();

    endsubmit; 
 quit;

要使用仅SAS解决方案回答您的问题,您的问题有两个:

使用SCAN而不是substr获取未加逗号/引号的部分 acct_nbr是一个数字,因此需要从输入中删除最终引号。 以下是我更改目录的正确代码,您需要将其更改回:

filename data 'c:\temp\json.txt';
data testdata2;
    infile data lrecl = 32000 truncover scanover;
        input 
            @'"acct_nbr": ' acct_nbr $255.
            @'"streetAddress": "' streetAddress $255. 
            @'"city": "' city $255. 
            @'"state": "' state $2. 
            @'"postalCode": "' postalCode $255.;

        acct_nbr=scan(acct_nbr,1,',"');
        streetAddress = scan(streetAddress,1,',"');
        city = scan(city,1,',"');
        state = scan(state,1,',"');
        postalCode = scan(postalCode,1,',"');
run;

proc print data=testdata2;
RUN;

要使用仅SAS解决方案回答您的问题,您的问题有两个:

使用SCAN而不是substr获取未加逗号/引号的部分 acct_nbr是一个数字,因此需要从输入中删除最终引号。 以下是我更改目录的正确代码,您需要将其更改回:

filename data 'c:\temp\json.txt';
data testdata2;
    infile data lrecl = 32000 truncover scanover;
        input 
            @'"acct_nbr": ' acct_nbr $255.
            @'"streetAddress": "' streetAddress $255. 
            @'"city": "' city $255. 
            @'"state": "' state $2. 
            @'"postalCode": "' postalCode $255.;

        acct_nbr=scan(acct_nbr,1,',"');
        streetAddress = scan(streetAddress,1,',"');
        city = scan(city,1,',"');
        state = scan(state,1,',"');
        postalCode = scan(postalCode,1,',"');
run;

proc print data=testdata2;
RUN;

我在sas.com上的一个线程中使用了这个json文件和上面的代码作为示例。那里的一位专家程序员非常慷慨,想出了一个解决方案。注意,json文件应包装在{}中

链接:

代码:


我在sas.com上的一个线程中使用了这个json文件和上面的代码作为示例。那里的一位专家程序员非常慷慨,想出了一个解决方案。注意,json文件应包装在{}中

链接:

代码:


@JohnChrysostom我使用此链接作为参考,但没有得到输出。。。。如果可能的话,你能提供一个样本吗…我们不会为你写代码。。。这不是StackOverflow的目的。如果您想发布您已经尝试过的内容并列出具体问题,我们将很乐意提供帮助。是的……对……我忘记添加代码了。。。。。刚刚编辑…请检查..如果我在输入@行中添加帐户编号。。。我在dataset中得到0个观察结果:@JohnChrysostom我使用此链接作为引用,但没有得到输出。。。。如果可能的话,你能提供一个样本吗…我们不会为你写代码。。。这不是StackOverflow的目的。如果您想发布您已经尝试过的内容并列出具体问题,我们将很乐意提供帮助。是的……对……我忘记添加代码了。。。。。刚刚编辑…请检查..如果我在输入@行中添加帐户编号。。。我在数据集中得到了0个观察值:awsm@Joe。。。扫描正在为我工作。。。但是我想要的输出是非常不同的。。。。请检查我的问题部分。。。我写了,我希望SAS数据集中的地址字段的输出如下:。。。这实际上是我想在SAS数据集中显示的。。。我的代码或您的代码正在生成解析json的输出。。那很好。。。但我需要一种旋转方式…所有列名和值都显示在同一行中…使用输出来获得所需的输出。这会产生多行,只需将不同的值放入您希望调用的变量中,然后输出每一行。如果您对此感到困惑,请提出一个新问题,因为这与json解析无关。awsm@Joe。。。扫描正在为我工作。。。但是我想要的输出是非常不同的。。。。请检查我的问题部分。。。我写了,我希望SAS数据集中的地址字段的输出如下:。。。这实际上是我想在SAS数据集中显示的。。。我的代码或您的代码正在生成解析json的输出。。那很好。。。但我需要一种旋转方式…所有列名和值都显示在同一行中…使用输出来获得所需的输出。这会产生多行,只需将不同的值放入您希望调用的变量中,然后输出每一行。如果您对此感到困惑,请提出一个新问题,因为这与json解析无关。。。让我用你的代码测试一下…a
我会在这里更新。。。thanx@Joe用于多个解决方案…:我欠你的…即使我不知道groovy。。。让我测试你的代码…我会在这里更新。。。thanx@Joe用于多个解决方案…:我欠你。。。