2016-10-26 1 views
1

Prolog에서 간단한 웹 서비스로 작업하고 있으며 사용자에게 JSON 형식의 데이터로 응답하고 싶습니다. 좋은 기능은 reply_json_dict/1입니다. 사전을 가져 와서 잘 형식화 된 JSON 본문을 사용하여 HTTP 응답으로 변환합니다.swi-prolog에서 사전 사용하기

제 문제는 응답 사전 자체를 작성하는 것이 약간 번거로운 것 같습니다. 예를 들어 일부 데이터를 반환 할 때 데이터 ID가 있지만 데이터 속성 (가능하면 언 바운드 변수)이 있거나 없을 수 있습니다. 나는 쉬운 방법을 찾고 있어요 ... 잘 작동하므로 출력 Props가 바인딩 여부 따라 { "id" : "III" } 또는 { "id" : "III", "attributes" : "AAA" }이지만,

OutDict0 = _{ id : DataId }, 
(nonvar(Props) -> OutDict1 = OutDict0.put(_{ attributes : Props }) ; OutDict1 = OutDict0), 
reply_json_dict(OutDict1) 

: 순간 나는 다음을 수행합니다. 주로 내가 더 선택 키/값 쌍을 추가해야하는 경우 때문에, 내가 좋아하는 여러 의미로 끝날 :

OutDict0 = _{ id : DataId }, 
(nonvar(Props) -> OutDict1 = OutDict0.put(_{ attributes : Props }) ; OutDict1 = OutDict0), 
(nonvar(Time) -> OutDict2 = OutDict1.put(_{ time : Time }) ; OutDict2 = OutDict1), 
(nonvar(UserName) -> OutDict3 = OutDict2.put(_{ userName : UserName }) ; OutDict3 = OutDict2), 
reply_json_dict(OutDict3) 

그리고 그것은 단지 잘못된 것 같습니다. 더 간단한 방법이 있습니까?

건배, 제이 섹 대신 사전 덤비는의

답변

1

많은 감사의 말씀을 전합니다.

dict_filter_vars(DictIn, DictOut) :- 
    findall(Key=Value, (get_dict(Key, DictIn, Value), nonvar(Value)), Pairs), 
    dict_create(DictOut, _, Pairs). 

그때는 그렇게 간단 사용할 수 있습니다 : 깔끔한 외모

DictWithVars = _{ id : DataId, attributes : Props, time : Time, userName : UserName }, 
dict_filter_vars(DictWithVars, DictOut), 
reply_json_dict(DictOut) 
+0

이 입력으로 해결해 주셔서 감사합니다! 그래도 문제는 여전히 남아 있습니다. 필요한 목록이 이미있는 경우에도 왜 사전을 만드시겠습니까? dicts는 Prolog의 표준 기능이 아니기 때문에 dict을 사용할 때마다 dict를 사용할 때마다 응용 프로그램의 이식성이 떨어집니다. – mat

+0

좋은 점은 비록 현재 이식성에 대해 덜 우려하고 있지만. dict에 대한 좋은 점은 키를 고유하게 유지하므로 JSON 객체에 매핑하는 것이 더 자연 스럽습니다. JSON 표준은 고유하지 않은 키를 허용하지만 많은 라이브러리는 그렇지 않으므로 고유하게 유지하는 것이 좋습니다. – Jacek

+0

'findall'의 첫 번째 인수에서'Key = Value'를 괄호로 묶지 않아도됩니다. –

3

,이 경우 내 추천   JSON을 방출하는 다른 술어를 사용하는 것입니다.

예를 들어 HTTP   라이브러리에 필요한대로 현재 출력에서 ​​JSON을 내보낼 수있는 json_write/2을 고려하십시오.

데이터 필드의 당신의 표현은 일반적인 Name(Value) 옵션 처리를 위해 HTTP 라이브러리 전반에 걸쳐 사용되는 표기법 가정 다음 include/3를 사용

 
Fields0 = [attributes(Props),time(Time),userName(UserName)], 

, 전체 예제가된다 :

 
main :- 
     Fields0 = [id(DataId),attributes(Props),time(Time),userName(UserName)], 
     include(ground, Fields0, Fields), 
     json_write(current_output, json(Fields)). 

sin 인 개별 요소에 적합한 값을 연결하여 직접 사용해 볼 수 있습니다. gleton 변수 위의 스 니펫에 있습니다.

 
     Fields0 = [id(i9),attributes(_),time('12:00'),userName(_)], 

는 산출 : 예를 들어

, 우리는 (임의)를 사용할 수있는 경우에만 적합한 콘텐츠 형식을 헤더를 방출 할 필요가

 
?- main. 
{"id":"i9", "time":"12:00"} 
true. 

, 동일한 출력을 가지고 그 reply_json_dict/1입니다.

+1

, 좋은 제안, 덕분에 나는 아이디어의 조합으로 끝났다. 지금은 사전에 조금 붙어 있습니다. 자신의 방식대로 코드를 다시 작성하는 데 드는 비용을 판단하려고합니다. 건배, Jacek – Jacek

+2

좋아요! 필요한 변경 사항은 극히 지역적입니다. 나머지 모든 코드가 사전을 사용하는 경우에도 사전의 목록 * 대신 *을 작성하여 개요의 값을 출력 할 수 있습니다. – mat

+1

@Jacek'dict_create (D, _, Fields)'로 필터링 된 목록의 사전을 만들거나'D = D0.put (Fields) '를 사용하여 목록의 요소를 기존의 dict에 추가 할 수 있습니다. –

2

목록을 사용하여 dict에 들어가야하는 모든 값을 나타내는 경우 한 단계로 수행 할 수 있습니다.

?- Props = [a,b,c], get_time(Time), 
    D0 = _{id:001}, 
    include(ground, [props:Props,time:Time,user:UserName], Fs), 
    D = D0.put(Fs). 
D0 = _17726{id:1}, 
Fs = [props:[a, b, c], time:1477557597.205908], 
D = _17726{id:1, props:[a, b, c], time:1477557597.205908}. 

매트의 답변에 include(ground)이라는 아이디어를 빌려줍니다.